@@ -16,7 +16,7 @@ import (
1616/*
1717Data struct to configure dump behavior
1818
19- Out: Stream to wite to
19+ Out: Stream to write to
2020 Connection: Database connection to dump
2121 IgnoreTables: Mark sensitive tables to ignore
2222 MaxAllowedPacket: Sets the largest packet size to use in backups
@@ -31,14 +31,16 @@ type Data struct {
3131
3232 tx * sql.Tx
3333 headerTmpl * template.Template
34+ viewTmpl * template.Template
3435 tableTmpl * template.Template
3536 footerTmpl * template.Template
3637 err error
3738}
3839
3940type table struct {
40- Name string
41- Err error
41+ Name string
42+ Err error
43+ isView bool
4244
4345 cols []string
4446 data * Data
@@ -115,6 +117,17 @@ LOCK TABLES {{ .NameEsc }} WRITE;
115117/*!40000 ALTER TABLE {{ .NameEsc }} ENABLE KEYS */;
116118UNLOCK TABLES;
117119`
120+ const viewTmpl = `
121+ --
122+ -- View structure for view {{ .NameEsc }}
123+ --
124+
125+ DROP VIEW IF EXISTS {{ .NameEsc }};
126+ /*!40101 SET @saved_cs_client = @@character_set_client */;
127+ SET character_set_client = utf8mb4 ;
128+ {{ .CreateSQL }};
129+ /*!40101 SET character_set_client = @saved_cs_client */;
130+ `
118131
119132const nullType = "NULL"
120133
@@ -133,7 +146,7 @@ func (data *Data) Dump() error {
133146 }
134147
135148 // Start the read only transaction and defer the rollback until the end
136- // This way the database will have the exact state it did at the begining of
149+ // This way the database will have the exact state it did at the beginning of
137150 // the backup and nothing can be accidentally committed
138151 if err := data .begin (); err != nil {
139152 return err
@@ -157,11 +170,11 @@ func (data *Data) Dump() error {
157170 if data .LockTables && len (tables ) > 0 {
158171 var b bytes.Buffer
159172 b .WriteString ("LOCK TABLES " )
160- for index , name := range tables {
173+ for index , table := range tables {
161174 if index != 0 {
162175 b .WriteString ("," )
163176 }
164- b .WriteString ("`" + name + "` READ /*!32311 LOCAL */" )
177+ b .WriteString ("`" + table . Name + "` READ /*!32311 LOCAL */" )
165178 }
166179
167180 if _ , err := data .Connection .Exec (b .String ()); err != nil {
@@ -171,11 +184,12 @@ func (data *Data) Dump() error {
171184 defer data .Connection .Exec ("UNLOCK TABLES" )
172185 }
173186
174- for _ , name := range tables {
175- if err := data .dumpTable (name ); err != nil {
187+ for _ , table := range tables {
188+ if err := data .dumpTable (table ); err != nil {
176189 return err
177190 }
178191 }
192+
179193 if data .err != nil {
180194 return data .err
181195 }
@@ -201,19 +215,24 @@ func (data *Data) rollback() error {
201215 return data .tx .Rollback ()
202216}
203217
204- // MARK: writter methods
218+ // MARK: writer methods
205219
206- func (data * Data ) dumpTable (name string ) error {
220+ func (data * Data ) dumpTable (table * table ) error {
207221 if data .err != nil {
208222 return data .err
209223 }
210- table := data .createTable (name )
211224 return data .writeTable (table )
212225}
213226
214227func (data * Data ) writeTable (table * table ) error {
215- if err := data .tableTmpl .Execute (data .Out , table ); err != nil {
216- return err
228+ if table .isView {
229+ if err := data .viewTmpl .Execute (data .Out , table ); err != nil {
230+ return err
231+ }
232+ } else {
233+ if err := data .tableTmpl .Execute (data .Out , table ); err != nil {
234+ return err
235+ }
217236 }
218237 return table .Err
219238}
@@ -232,29 +251,36 @@ func (data *Data) getTemplates() (err error) {
232251 return
233252 }
234253
254+ data .viewTmpl , err = template .New ("mysqldumpView" ).Parse (viewTmpl )
255+ if err != nil {
256+ return
257+ }
258+
235259 data .footerTmpl , err = template .New ("mysqldumpTable" ).Parse (footerTmpl )
236260 if err != nil {
237261 return
238262 }
239263 return
240264}
241265
242- func (data * Data ) getTables () ([]string , error ) {
243- tables := make ([]string , 0 )
266+ func (data * Data ) getTables () ([]* table , error ) {
267+ tables := make ([]* table , 0 )
244268
245- rows , err := data .tx .Query ("SHOW TABLES" )
269+ rows , err := data .tx .Query ("SHOW FULL TABLES" )
246270 if err != nil {
247271 return tables , err
248272 }
249273 defer rows .Close ()
250274
251275 for rows .Next () {
252- var table sql.NullString
253- if err := rows .Scan (& table ); err != nil {
276+ var tableName sql.NullString
277+ var tableType sql.NullString
278+ if err := rows .Scan (& tableName , & tableType ); err != nil {
254279 return tables , err
255280 }
256- if table .Valid && ! data .isIgnoredTable (table .String ) {
257- tables = append (tables , table .String )
281+ if tableName .Valid && ! data .isIgnoredTable (tableName .String ) {
282+ table := data .createTable (tableName .String , tableType .String == "VIEW" )
283+ tables = append (tables , table )
258284 }
259285 }
260286 return tables , rows .Err ()
@@ -278,10 +304,11 @@ func (meta *metaData) updateServerVersion(data *Data) (err error) {
278304
279305// MARK: create methods
280306
281- func (data * Data ) createTable (name string ) * table {
307+ func (data * Data ) createTable (name string , isView bool ) * table {
282308 return & table {
283- Name : name ,
284- data : data ,
309+ Name : name ,
310+ isView : isView ,
311+ data : data ,
285312 }
286313}
287314
@@ -323,6 +350,8 @@ func (table *table) CreateSQL() (string, error) {
323350 return "" , errors .New ("returned table is not the same as requested table" )
324351 }
325352
353+ table .isView = strings .Contains (info [1 ].String , "VIEW" )
354+
326355 return info [1 ].String , nil
327356}
328357
@@ -413,7 +442,7 @@ func (table *table) Init() error {
413442}
414443
415444func reflectColumnType (tp * sql.ColumnType ) reflect.Type {
416- // reflect for scanable
445+ // reflect for ScanType
417446 switch tp .ScanType ().Kind () {
418447 case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
419448 return reflect .TypeOf (sql.NullInt64 {})
0 commit comments