This repository has been archived by the owner on Sep 20, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
database_mysql.go
158 lines (145 loc) · 3.92 KB
/
database_mysql.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package table_doc
import (
"database/sql"
"errors"
"fmt"
mysql_driver "github.com/go-sql-driver/mysql"
"regexp"
"strings"
)
type mysql struct {
db *sql.DB
config *MySQLConfig
}
func (m *mysql) Close() {
m.db.Close()
}
type MySQLConfig struct {
DatabaseSchemaConfig
Config *mysql_driver.Config
}
func (config *MySQLConfig) String() string {
return config.Config.FormatDSN()
}
func (config *MySQLConfig) Databese() (Database, error) {
db, err := sql.Open("mysql", config.String())
if err != nil {
return nil, errors.New(fmt.Sprintf("MySQLConfig#Databese: fail to open pmysql connection. %s", err.Error()))
}
return &mysql{db: db, config: config}, nil
}
func (m *mysql) tableDefinition(schemaName string, tableName string) (string, error) {
var definition string
err := m.db.QueryRow(fmt.Sprintf("SHOW CREATE TABLE %s.%s", schemaName, tableName)).Scan(&tableName, &definition)
if err != nil {
return "", err
}
reg := regexp.MustCompile(`AUTO_INCREMENT=[0-9]+ `)
return reg.ReplaceAllString(definition, ""), nil
}
func (m *mysql) viewDefinition(schemaName string, tableName string) (string, error) {
var definition string
err := m.db.QueryRow("SELECT VIEW_DEFINITION FROM information_schema.VIEWS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?", schemaName, tableName).Scan(&definition)
if err != nil {
return "", err
}
definition = fmt.Sprintf("create or replace view %s AS %s", tableName, definition)
for _, phrase := range []string{
"select",
"from",
"union",
"where",
"order by",
"group by",
"having",
"procedure",
"for update",
"lock in share mode",
} {
definition = strings.Replace(definition, phrase, "\n " + phrase, -1)
}
return definition, nil
}
func (m *mysql) columns(schemaName string, tableName string) ([]*Column, error) {
rows, err := m.db.Query("SELECT ORDINAL_POSITION, COLUMN_NAME, COLUMN_TYPE, COALESCE(COLUMN_DEFAULT, 'null'), IS_NULLABLE, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION", schemaName, tableName)
defer rows.Close()
if err != nil {
return nil, err
}
var columns []*Column
for rows.Next() {
var columnPosition uint
var columnName string
var columnType string
var columnDefault string
var columnNullable string
var columnComment string
if err := rows.Scan(&columnPosition, &columnName, &columnType, &columnDefault, &columnNullable, &columnComment); err != nil {
return nil, err
}
column := Column{
Position: columnPosition,
Name: columnName,
Type: columnType,
Default: columnDefault,
Nullable: columnNullable,
Comment: columnComment,
}
columns = append(columns, &column)
}
return columns, nil
}
func (m *mysql) tables(schemaName string) ([]*Table, error) {
rows, err := m.db.Query("SELECT TABLE_NAME, TABLE_TYPE, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?", schemaName)
defer rows.Close()
if err != nil {
return nil, err
}
var tables []*Table
for rows.Next() {
var err error
var tableName string
var tableType string
var tableComment string
if err = rows.Scan(&tableName, &tableType, &tableComment); err != nil {
return nil, err
}
table := Table{
Name: tableName,
Type: tableType,
Comment: tableComment,
}
table.Columns, err = m.columns(schemaName, table.Name)
if err != nil {
return nil, err
}
if table.Type == "VIEW" {
table.Definition, err = m.viewDefinition(schemaName, table.Name)
if err != nil {
return nil, err
}
} else {
table.Definition, err = m.tableDefinition(schemaName, table.Name)
if err != nil {
return nil, err
}
}
tables = append(tables, &table)
}
return tables, nil
}
func (m *mysql) Schemas() ([]*Schema, error) {
var ss []*Schema
for alias, name := range m.config.Names() {
tables, err := m.tables(name)
if err != nil {
return nil, err
}
s := Schema{
Name: alias,
Tables: tables,
}
ss = append(ss, &s)
}
return ss, nil
}