PageRenderTime 2143ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/db/conn.go

https://gitlab.com/github-cloud-corporation/dex
Go | 110 lines | 85 code | 13 blank | 12 comment | 17 complexity | 654f19da3b0bfd2328578df1da44f763 MD5 | raw file
  1. package db
  2. import (
  3. "database/sql"
  4. "errors"
  5. "fmt"
  6. "net/url"
  7. "github.com/go-gorp/gorp"
  8. "github.com/coreos/dex/repo"
  9. )
  10. type table struct {
  11. name string
  12. model interface{}
  13. autoinc bool
  14. pkey []string
  15. // unique are non-primary key fields which should have uniqueness constraints.
  16. unique []string
  17. }
  18. var (
  19. tables []table
  20. )
  21. func register(t table) {
  22. tables = append(tables, t)
  23. }
  24. type Config struct {
  25. // Connection string in the format: <driver>://<username>:<password>@<host>:<port>/<database>
  26. DSN string
  27. // The maximum number of open connections to the database. The default is 0 (unlimited).
  28. // For more details see: http://golang.org/pkg/database/sql/#DB.SetMaxOpenConns
  29. MaxOpenConnections int
  30. // The maximum number of connections in the idle connection pool. The default is 0 (unlimited).
  31. // For more details see: http://golang.org/pkg/database/sql/#DB.SetMaxIdleConns
  32. MaxIdleConnections int
  33. }
  34. func NewConnection(cfg Config) (*gorp.DbMap, error) {
  35. u, err := url.Parse(cfg.DSN)
  36. if err != nil {
  37. return nil, fmt.Errorf("parse DSN: %v", err)
  38. }
  39. var (
  40. db *sql.DB
  41. dialect gorp.Dialect
  42. )
  43. switch u.Scheme {
  44. case "postgres":
  45. db, err = sql.Open("postgres", cfg.DSN)
  46. if err != nil {
  47. return nil, err
  48. }
  49. db.SetMaxIdleConns(cfg.MaxIdleConnections)
  50. db.SetMaxOpenConns(cfg.MaxOpenConnections)
  51. dialect = gorp.PostgresDialect{}
  52. case "sqlite3":
  53. db, err = sql.Open("sqlite3", u.Host)
  54. if err != nil {
  55. return nil, err
  56. }
  57. if u.Host == ":memory:" {
  58. // NOTE(ericchiang): sqlite3 coordinates concurrent clients through file locks.
  59. // In memory databases do not support concurrent calls. Limit the number of
  60. // open connections to 1.
  61. //
  62. // See: https://www.sqlite.org/faq.html#q5
  63. db.SetMaxOpenConns(1)
  64. }
  65. dialect = gorp.SqliteDialect{}
  66. default:
  67. return nil, errors.New("unrecognized database driver")
  68. }
  69. dbm := gorp.DbMap{Db: db, Dialect: dialect}
  70. for _, t := range tables {
  71. tm := dbm.AddTableWithName(t.model, t.name).SetKeys(t.autoinc, t.pkey...)
  72. for _, unique := range t.unique {
  73. cm := tm.ColMap(unique)
  74. if cm == nil {
  75. return nil, fmt.Errorf("no such column: %q", unique)
  76. }
  77. cm.SetUnique(true)
  78. }
  79. }
  80. return &dbm, nil
  81. }
  82. func TransactionFactory(conn *gorp.DbMap) repo.TransactionFactory {
  83. return func() (repo.Transaction, error) {
  84. return conn.Begin()
  85. }
  86. }
  87. // NewMemDB creates a new in memory sqlite3 database.
  88. func NewMemDB() *gorp.DbMap {
  89. dbMap, err := NewConnection(Config{DSN: "sqlite3://:memory:"})
  90. if err != nil {
  91. panic("Failed to create in memory database: " + err.Error())
  92. }
  93. if _, err := MigrateToLatest(dbMap); err != nil {
  94. panic("In memory database migration failed: " + err.Error())
  95. }
  96. return dbMap
  97. }