11package db
22
33import (
4- "context"
54 "errors"
65 "fmt"
76 "log"
@@ -13,55 +12,55 @@ import (
1312 "time"
1413
1514 "github.com/jinzhu/gorm"
16- "github.com/mattn/go-sqlite3"
15+ _ "github.com/jinzhu/gorm/dialects/postgres"
16+ _ "github.com/jinzhu/gorm/dialects/sqlite"
1717
1818 // TODO: remove this dep
1919 "go.senan.xyz/gonic/server/ctrlsubsonic/specid"
2020)
2121
22- func DefaultOptions () url.Values {
23- return url.Values {
24- // with this, multiple connections share a single data and schema cache.
25- // see https://www.sqlite.org/sharedcache.html
26- "cache" : {"shared" },
27- // with this, the db sleeps for a little while when locked. can prevent
28- // a SQLITE_BUSY. see https://www.sqlite.org/c3ref/busy_timeout.html
29- "_busy_timeout" : {"30000" },
30- "_journal_mode" : {"WAL" },
31- "_foreign_keys" : {"true" },
32- }
22+ type DB struct {
23+ * gorm.DB
3324}
3425
35- func mockOptions () url. Values {
36- return url. Values {
37- "_foreign_keys" : { "true" },
26+ func New ( uri string ) ( * DB , error ) {
27+ if uri == "" {
28+ return nil , fmt . Errorf ( "empty db uri" )
3829 }
39- }
4030
41- type DB struct {
42- * gorm.DB
43- }
31+ url , err := url .Parse (uri )
32+ if err != nil {
33+ return nil , fmt .Errorf ("parse uri: %w" , err )
34+ }
4435
45- func New (path string , options url.Values ) (* DB , error ) {
46- // https://github.com/mattn/go-sqlite3#connection-string
47- url := url.URL {
48- Scheme : "file" ,
49- Opaque : path ,
36+ gormUrl := strings .TrimPrefix (url .String (), url .Scheme + "://" )
37+
38+ //nolint:goconst
39+ switch url .Scheme {
40+ case "sqlite3" :
41+ q := url .Query ()
42+ q .Set ("cache" , "shared" )
43+ q .Set ("_busy_timeout" , "30000" )
44+ q .Set ("_journal_mode" , "WAL" )
45+ q .Set ("_foreign_keys" , "true" )
46+ url .RawQuery = q .Encode ()
47+ case "postgres" :
48+ // the postgres driver expects the schema prefix to be on the URL
49+ gormUrl = url .String ()
50+ default :
51+ return nil , fmt .Errorf ("unknown db scheme" )
5052 }
51- url . RawQuery = options . Encode ()
52- db , err := gorm .Open ("sqlite3" , url .String () )
53+
54+ db , err := gorm .Open (url .Scheme , gormUrl )
5355 if err != nil {
5456 return nil , fmt .Errorf ("with gorm: %w" , err )
5557 }
58+
5659 db .SetLogger (log .New (os .Stdout , "gorm " , 0 ))
5760 db .DB ().SetMaxOpenConns (1 )
5861 return & DB {DB : db }, nil
5962}
6063
61- func NewMock () (* DB , error ) {
62- return New (":memory:" , mockOptions ())
63- }
64-
6564func (db * DB ) InsertBulkLeftMany (table string , head []string , left int , col []int ) error {
6665 if len (col ) == 0 {
6766 return nil
@@ -72,10 +71,11 @@ func (db *DB) InsertBulkLeftMany(table string, head []string, left int, col []in
7271 rows = append (rows , "(?, ?)" )
7372 values = append (values , left , c )
7473 }
75- q := fmt .Sprintf ("INSERT OR IGNORE INTO %q (%s) VALUES %s" ,
74+ q := fmt .Sprintf ("INSERT INTO %q (%s) VALUES %s ON CONFLICT (%s) DO NOTHING " ,
7675 table ,
7776 strings .Join (head , ", " ),
7877 strings .Join (rows , ", " ),
78+ strings .Join (head , ", " ),
7979 )
8080 return db .Exec (q , values ... ).Error
8181}
@@ -611,45 +611,3 @@ func join[T fmt.Stringer](in []T, sep string) string {
611611 }
612612 return strings .Join (strs , sep )
613613}
614-
615- func Dump (ctx context.Context , db * gorm.DB , to string ) error {
616- dest , err := New (to , url.Values {})
617- if err != nil {
618- return fmt .Errorf ("create dest db: %w" , err )
619- }
620- defer dest .Close ()
621-
622- connSrc , err := db .DB ().Conn (ctx )
623- if err != nil {
624- return fmt .Errorf ("getting src raw conn: %w" , err )
625- }
626- defer connSrc .Close ()
627-
628- connDest , err := dest .DB .DB ().Conn (ctx )
629- if err != nil {
630- return fmt .Errorf ("getting dest raw conn: %w" , err )
631- }
632- defer connDest .Close ()
633-
634- err = connDest .Raw (func (connDest interface {}) error {
635- return connSrc .Raw (func (connSrc interface {}) error {
636- connDestq := connDest .(* sqlite3.SQLiteConn )
637- connSrcq := connSrc .(* sqlite3.SQLiteConn )
638- bk , err := connDestq .Backup ("main" , connSrcq , "main" )
639- if err != nil {
640- return fmt .Errorf ("create backup db: %w" , err )
641- }
642- for done , _ := bk .Step (- 1 ); ! done ; { //nolint: revive
643- }
644- if err := bk .Finish (); err != nil {
645- return fmt .Errorf ("finishing dump: %w" , err )
646- }
647- return nil
648- })
649- })
650- if err != nil {
651- return fmt .Errorf ("backing up: %w" , err )
652- }
653-
654- return nil
655- }
0 commit comments