This repository has been archived by the owner on Nov 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmysql.go
130 lines (114 loc) · 3.62 KB
/
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
package parse
import (
"context"
"database/sql"
"fmt"
"log"
// Include MySQL driver in order to connect to it in NewMySQL
_ "github.com/go-sql-driver/mysql"
"github.com/weworksandbox/lingo/dialect"
"github.com/weworksandbox/lingo/internal/generator"
)
func NewMySQL(ctx context.Context, dsn string) (*MySQL, error) {
db, err := sql.Open("mysql", dsn)
if err != nil {
return nil, err
}
if err = db.PingContext(ctx); err != nil {
return nil, err
}
return &MySQL{db: db}, nil
}
type MySQL struct {
dialect.MySQL
db *sql.DB
}
func (MySQL) DBTypesToPaths() map[string]generator.PathPackageToType {
const pkgCorePath = "github.com/weworksandbox/lingo/expr/path"
// TODO - Need to do further changes to Paths. Right now, every Path can have nullable operations against it.
// We may want to create a `Int64NullPath` vs `Int64Path` for example. In that case, `Int64NullPath` just extends
// and adds the nullable methods? https://github.com/go-sql-driver/mysql/blob/master/fields.go
// Note: For `decimal`, we create our own, but there is no 'decimal' type in Go
// besides `math/big/decimal.go` which is binary anyway...
return map[string]generator.PathPackageToType{
"BIGINT": {pkgCorePath, "Int64"},
"BINARY": {pkgCorePath, "Binary"},
"CHAR": {pkgCorePath, "String"},
"DATETIME": {pkgCorePath, "Time"},
"DECIMAL": {pkgCorePath, "Binary"}, // See note above.
"DOUBLE": {pkgCorePath, "Float64"},
"FLOAT": {pkgCorePath, "Float32"},
"INT": {pkgCorePath, "Int"},
"JSON": {pkgCorePath, "JSON"},
"MEDIUMINT": {pkgCorePath, "Int32"},
"SMALLINT": {pkgCorePath, "Int16"},
"TEXT": {pkgCorePath, "String"},
"TINYINT": {pkgCorePath, "Int8"},
"TIMESTAMP": {pkgCorePath, "Time"},
"VARCHAR": {pkgCorePath, "String"},
}
}
func (m MySQL) Tables(ctx context.Context, schema string) ([]string, error) {
const selectQuery = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?"
sqlStmt, prepareErr := m.db.PrepareContext(ctx, selectQuery)
if prepareErr != nil {
return nil, prepareErr
}
defer func() {
if closeErr := sqlStmt.Close(); closeErr != nil {
log.Printf("unable to close `findTables` query: %v", closeErr)
}
}()
rows, queryErr := sqlStmt.QueryContext(ctx, schema)
if queryErr != nil {
return nil, queryErr
}
defer func() {
if closeErr := rows.Close(); closeErr != nil {
log.Printf("unable to close `rows` during `findTables` query: %v", closeErr)
}
}()
var tables []string
for rows.Next() {
var tableName string
if scanErr := rows.Scan(&tableName); scanErr != nil {
return nil, scanErr
}
tables = append(tables, tableName)
}
return tables, nil
}
func (m MySQL) Columns(ctx context.Context, schema, table string) ([]generator.Column, error) {
sqlStr := fmt.Sprintf("SELECT * FROM %s.%s LIMIT 0", schema, table)
sqlStmt, prepareErr := m.db.PrepareContext(ctx, sqlStr)
if prepareErr != nil {
return nil, prepareErr
}
defer func() {
if closeErr := sqlStmt.Close(); closeErr != nil {
log.Printf("unable to close `findColumns` query: %v", closeErr)
}
}()
rows, queryErr := sqlStmt.QueryContext(ctx)
if queryErr != nil {
return nil, queryErr
}
defer func() {
if closeErr := rows.Close(); closeErr != nil {
log.Printf("unable to close `rows` during `findColumns` query: %v", closeErr)
}
}()
columnTypes, typesErr := rows.ColumnTypes()
if typesErr != nil {
return nil, typesErr
}
var columns = make([]generator.Column, 0, len(columnTypes))
for _, col := range columnTypes {
var columnInfo = Column{
table: table,
columnType: col,
}
columns = append(columns, columnInfo)
}
return columns, nil
}