forked from dexidp/dex
-
Notifications
You must be signed in to change notification settings - Fork 0
/
conn.go
110 lines (97 loc) · 2.66 KB
/
conn.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
package db
import (
"database/sql"
"errors"
"fmt"
"net/url"
"github.com/go-gorp/gorp"
"github.com/coreos/dex/repo"
)
type table struct {
name string
model interface{}
autoinc bool
pkey []string
// unique are non-primary key fields which should have uniqueness constraints.
unique []string
}
var (
tables []table
)
func register(t table) {
tables = append(tables, t)
}
type Config struct {
// Connection string in the format: <driver>://<username>:<password>@<host>:<port>/<database>
DSN string
// The maximum number of open connections to the database. The default is 0 (unlimited).
// For more details see: http://golang.org/pkg/database/sql/#DB.SetMaxOpenConns
MaxOpenConnections int
// The maximum number of connections in the idle connection pool. The default is 0 (unlimited).
// For more details see: http://golang.org/pkg/database/sql/#DB.SetMaxIdleConns
MaxIdleConnections int
}
func NewConnection(cfg Config) (*gorp.DbMap, error) {
u, err := url.Parse(cfg.DSN)
if err != nil {
return nil, fmt.Errorf("parse DSN: %v", err)
}
var (
db *sql.DB
dialect gorp.Dialect
)
switch u.Scheme {
case "postgres":
db, err = sql.Open("postgres", cfg.DSN)
if err != nil {
return nil, err
}
db.SetMaxIdleConns(cfg.MaxIdleConnections)
db.SetMaxOpenConns(cfg.MaxOpenConnections)
dialect = gorp.PostgresDialect{}
case "sqlite3":
db, err = sql.Open("sqlite3", u.Host)
if err != nil {
return nil, err
}
if u.Host == ":memory:" {
// NOTE(ericchiang): sqlite3 coordinates concurrent clients through file locks.
// In memory databases do not support concurrent calls. Limit the number of
// open connections to 1.
//
// See: https://www.sqlite.org/faq.html#q5
db.SetMaxOpenConns(1)
}
dialect = gorp.SqliteDialect{}
default:
return nil, errors.New("unrecognized database driver")
}
dbm := gorp.DbMap{Db: db, Dialect: dialect}
for _, t := range tables {
tm := dbm.AddTableWithName(t.model, t.name).SetKeys(t.autoinc, t.pkey...)
for _, unique := range t.unique {
cm := tm.ColMap(unique)
if cm == nil {
return nil, fmt.Errorf("no such column: %q", unique)
}
cm.SetUnique(true)
}
}
return &dbm, nil
}
func TransactionFactory(conn *gorp.DbMap) repo.TransactionFactory {
return func() (repo.Transaction, error) {
return conn.Begin()
}
}
// NewMemDB creates a new in memory sqlite3 database.
func NewMemDB() *gorp.DbMap {
dbMap, err := NewConnection(Config{DSN: "sqlite3://:memory:"})
if err != nil {
panic("Failed to create in memory database: " + err.Error())
}
if _, err := MigrateToLatest(dbMap); err != nil {
panic("In memory database migration failed: " + err.Error())
}
return dbMap
}