forked from wantedly/pq2gorm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpostgres.go
173 lines (142 loc) · 3.07 KB
/
postgres.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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package main
import (
"database/sql"
"strconv"
"strings"
_ "github.com/lib/pq"
)
type Postgres struct {
DB *sql.DB
}
type Field struct {
Name string
Type string
Default string
Nullable bool
}
func NewPostgres(url string) (*Postgres, error) {
db, err := sql.Open("postgres", url)
if err != nil {
return nil, err
}
return &Postgres{
DB: db,
}, nil
}
func (p *Postgres) retrieveAllTables() (*sql.Rows, error) {
return p.DB.Query(`select relname as TABLE_NAME from pg_stat_user_tables`)
}
func (p *Postgres) retrieveSelectedTables(targets []string) (*sql.Rows, error) {
qs := []string{}
params := []interface{}{}
for i, t := range targets {
qs = append(qs, "$"+strconv.Itoa(i+1))
params = append(params, t)
}
return p.DB.Query(`select relname as TABLE_NAME from pg_stat_user_tables where relname in (`+strings.Join(qs, ", ")+`)`, params...)
}
func (p *Postgres) RetrieveFields(table string) ([]*Field, error) {
query :=
`
select column_name, udt_name::regtype, COALESCE(column_default, '') as column_default, is_nullable
from information_schema.columns
where
table_name='` + table + `'
order by
ordinal_position;
`
rows, err := p.DB.Query(query)
if err != nil {
return nil, err
}
var (
columnName string
columnType string
columnDefault string
columnIsNullable string
)
var nullable bool
fields := []*Field{}
for rows.Next() {
err = rows.Scan(&columnName, &columnType, &columnDefault, &columnIsNullable)
if err != nil {
return nil, err
}
if columnIsNullable == "YES" {
nullable = true
} else {
nullable = false
}
field := &Field{
Name: columnName,
Type: columnType,
Default: columnDefault,
Nullable: nullable,
}
fields = append(fields, field)
}
return fields, nil
}
func (p *Postgres) RetrieveTables(targets []string) ([]string, error) {
var (
rows *sql.Rows
err error
)
if len(targets) == 0 {
rows, err = p.retrieveAllTables()
if err != nil {
return nil, err
}
} else {
rows, err = p.retrieveSelectedTables(targets)
if err != nil {
return nil, err
}
}
tables := []string{}
var table string
for rows.Next() {
err = rows.Scan(&table)
if err != nil {
return nil, err
}
tables = append(tables, table)
}
return tables, nil
}
func (p *Postgres) RetrievePrimaryKeys(table string) (map[string]bool, error) {
query :=
`
select
ccu.column_name as COLUMN_NAME
from
information_schema.table_constraints tc
,information_schema.constraint_column_usage ccu
where
tc.table_name='` + table + `'
and
tc.constraint_type='PRIMARY KEY'
and
tc.table_catalog=ccu.table_catalog
and
tc.table_schema=ccu.table_schema
and
tc.table_name=ccu.table_name
and
tc.constraint_name=ccu.constraint_name
`
rows, err := p.DB.Query(query)
if err != nil {
return nil, err
}
var column string
pkeys := map[string]bool{}
for rows.Next() {
err = rows.Scan(&column)
if err != nil {
return nil, err
}
pkeys[column] = true
}
return pkeys, nil
}