/
snowflake.go
132 lines (118 loc) · 2.85 KB
/
snowflake.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 snowflake
import (
"database/sql"
"github.com/k1LoW/tbls/schema"
"github.com/pkg/errors"
_ "github.com/snowflakedb/gosnowflake"
)
type Snowflake struct {
db *sql.DB
}
func New(db *sql.DB) *Snowflake {
return &Snowflake{
db: db,
}
}
func (sf *Snowflake) Analyze(s *schema.Schema) error {
d, err := sf.Info()
if err != nil {
return errors.WithStack(err)
}
s.Driver = d
tableRows, err := sf.db.Query(`SELECT table_name, table_type, comment FROM information_schema.tables WHERE table_schema = ? order by table_name`, s.Name)
if err != nil {
return errors.WithStack(err)
}
defer tableRows.Close()
tables := []*schema.Table{}
for tableRows.Next() {
var (
tableName string
tableType string
comment sql.NullString
)
if err := tableRows.Scan(&tableName, &tableType, &comment); err != nil {
return errors.WithStack(err)
}
table := &schema.Table{
Name: tableName,
Type: tableType,
Comment: comment.String,
}
var getDDLObjectType string
if tableType == "BASE TABLE" {
getDDLObjectType = "table"
} else if tableType == "VIEW" {
getDDLObjectType = "view"
}
if getDDLObjectType != "" {
tableDefRows, err := sf.db.Query(`SELECT GET_DDL(?, ?)`, getDDLObjectType, tableName)
if err != nil {
return errors.WithStack(err)
}
defer tableDefRows.Close()
for tableDefRows.Next() {
var tableDef string
err := tableDefRows.Scan(&tableDef)
if err != nil {
return errors.WithStack(err)
}
table.Def = tableDef
}
}
// columns, comments
columnRows, err := sf.db.Query(`select column_name, column_default, is_nullable, data_type, comment
from information_schema.columns
where table_schema = ? and table_name = ? order by ordinal_position`, s.Name, tableName)
if err != nil {
return errors.WithStack(err)
}
defer columnRows.Close()
columns := []*schema.Column{}
for columnRows.Next() {
var (
columnName string
columnDefault sql.NullString
isNullable string
dataType string
columnComment sql.NullString
)
err = columnRows.Scan(
&columnName,
&columnDefault,
&isNullable,
&dataType,
&columnComment,
)
if err != nil {
return errors.WithStack(err)
}
column := &schema.Column{
Name: columnName,
Type: dataType,
Nullable: convertColumnNullable(isNullable),
Default: columnDefault,
Comment: columnComment.String,
}
columns = append(columns, column)
}
table.Columns = columns
tables = append(tables, table)
}
s.Tables = tables
return nil
}
func (s *Snowflake) Info() (*schema.Driver, error) {
var v string
row := s.db.QueryRow(`SELECT CURRENT_VERSION();`)
if err := row.Scan(&v); err != nil {
return nil, err
}
return &schema.Driver{
Name: "snowflake",
DatabaseVersion: v,
}, nil
}
func convertColumnNullable(str string) bool {
return str != "NO"
}