-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
132 lines (109 loc) · 2.79 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"database/sql"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"time"
_ "github.com/go-sql-driver/mysql"
)
type Config struct {
Host string
Port int
User string
Password string
Database string
Output string
Print bool
}
func main() {
config := parseFlags()
if err := export(config); err != nil {
log.Fatal(err)
}
}
func parseFlags() *Config {
config := &Config{}
flag.StringVar(&config.Host, "h", "localhost", "MySQL host")
flag.IntVar(&config.Port, "p", 3306, "MySQL port")
flag.StringVar(&config.User, "u", "", "MySQL user")
flag.StringVar(&config.Password, "pass", "", "MySQL password")
flag.StringVar(&config.Database, "db", "", "Database name")
flag.StringVar(&config.Output, "out", "schema.sql", "Output file path")
flag.BoolVar(&config.Print, "print", false, "print schema")
flag.Parse()
if config.User == "" || config.Database == "" {
flag.Usage()
os.Exit(1)
}
return config
}
func export(config *Config) error {
if err := os.MkdirAll(config.Output, 0755); err != nil {
return fmt.Errorf("failed to create output directory: %w", err)
}
// Prepare output file path
outputPath := filepath.Join(config.Output, "schema.sql")
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s",
config.User,
config.Password,
config.Host,
config.Port,
config.Database,
)
db, err := sql.Open("mysql", dsn)
if err != nil {
return fmt.Errorf("failed to connect to database: %w", err)
}
defer db.Close()
// Get all table names
tables, err := getTables(db)
if err != nil {
return err
}
// Create output file
f, err := os.Create(outputPath)
if err != nil {
return fmt.Errorf("failed to create output file: %w", err)
}
defer f.Close()
if config.Print {
f = os.Stdin
}
// Write header
fmt.Fprintf(f, "-- Generated by schemaloader on %s\n", time.Now().Format("2006-01-02 15:04:05"))
fmt.Fprintf(f, "-- Database: %s\n\n", config.Database)
fmt.Fprintf(f, "SET FOREIGN_KEY_CHECKS=0;\n\n")
// Export each table
for _, table := range tables {
// Get create table statement
var tableSchema string
query := fmt.Sprintf("SHOW CREATE TABLE `%s`", table)
row := db.QueryRow(query)
var tableName string
if err := row.Scan(&tableName, &tableSchema); err != nil {
return fmt.Errorf("failed to get schema for table %s: %w", table, err)
}
fmt.Fprintf(f, "%s;\n\n", tableSchema)
}
fmt.Fprintf(f, "SET FOREIGN_KEY_CHECKS=1;\n")
return nil
}
func getTables(db *sql.DB) ([]string, error) {
rows, err := db.Query("SHOW TABLES")
if err != nil {
return nil, fmt.Errorf("failed to get tables: %w", err)
}
defer rows.Close()
var tables []string
for rows.Next() {
var table string
if err := rows.Scan(&table); err != nil {
return nil, fmt.Errorf("failed to scan table name: %w", err)
}
tables = append(tables, table)
}
return tables, nil
}