github.com/fragmenta/query@v1.5.3/adapters/database_psql.go (about) 1 package adapters 2 3 import ( 4 "database/sql" 5 "fmt" 6 7 // psql driver 8 _ "github.com/lib/pq" 9 ) 10 11 // PostgresqlAdapter conforms to the query.Database interface 12 type PostgresqlAdapter struct { 13 *Adapter 14 options map[string]string 15 sqlDB *sql.DB 16 debug bool 17 } 18 19 // Open this database with the given options 20 // opts map keys:adapter, user, password, db, host, port, params (give extra parameters in the params option) 21 // Additional options available are detailed in the pq driver docs at 22 // https://godoc.org/github.com/lib/pq 23 func (db *PostgresqlAdapter) Open(opts map[string]string) error { 24 25 db.debug = false 26 db.options = map[string]string{ 27 "adapter": "postgres", 28 "user": "", 29 "password": "", 30 "db": "", 31 "host": "localhost", // for unix instead of tcp use path - see driver 32 "port": "5432", // default PSQL port 33 "params": "sslmode=disable connect_timeout=60", // disable sslmode for localhost, set timeout 34 } 35 36 if opts["debug"] == "true" { 37 db.debug = true 38 } 39 40 // Merge options 41 for k, v := range opts { 42 db.options[k] = v 43 } 44 45 // Default to psql database on localhost on port 5432, typical connection string: 46 // user=server password=p host=localhost port=5432 dbname=db sslmode=disable 47 // See https://godoc.org/github.com/lib/pq for options, use params to override defaults if required 48 optionString := fmt.Sprintf("user=%s %s host=%s port=%s dbname=%s %s", 49 db.options["user"], 50 paramOrBlank("password", db.options["password"]), 51 db.options["host"], 52 db.options["port"], 53 db.options["db"], 54 db.options["params"]) 55 56 var err error 57 db.sqlDB, err = sql.Open(db.options["adapter"], optionString) 58 if err != nil { 59 return err 60 } 61 62 // Call ping on the db to check it does actually exist! 63 err = db.sqlDB.Ping() 64 if err != nil { 65 return err 66 } 67 68 if db.sqlDB != nil && db.debug { 69 fmt.Printf("Database %s opened using %s\n", db.options["db"], db.options["adapter"]) 70 } 71 72 return nil 73 74 } 75 76 func paramOrBlank(k, v string) string { 77 if len(v) > 0 { 78 return fmt.Sprintf("%s=%s", k, v) 79 } 80 return "" 81 } 82 83 // Close the database 84 func (db *PostgresqlAdapter) Close() error { 85 if db.sqlDB != nil { 86 return db.sqlDB.Close() 87 } 88 return nil 89 } 90 91 // SQLDB returns the internal db.sqlDB pointer 92 func (db *PostgresqlAdapter) SQLDB() *sql.DB { 93 return db.sqlDB 94 } 95 96 // Query executes query SQL - NB caller must call use defer rows.Close() with rows returned 97 func (db *PostgresqlAdapter) Query(query string, args ...interface{}) (*sql.Rows, error) { 98 return db.performQuery(db.sqlDB, db.debug, query, args...) 99 } 100 101 // Exec - use this for non-select statements 102 func (db *PostgresqlAdapter) Exec(query string, args ...interface{}) (sql.Result, error) { 103 return db.performExec(db.sqlDB, db.debug, query, args...) 104 } 105 106 // Placeholder returns the db placeholder 107 func (db *PostgresqlAdapter) Placeholder(i int) string { 108 return fmt.Sprintf("$%d", i) 109 } 110 111 // InsertSQL is extra SQL for end of insert statement (RETURNING for psql) 112 func (db *PostgresqlAdapter) InsertSQL(pk string) string { 113 return fmt.Sprintf("RETURNING %s", pk) 114 } 115 116 // Insert a record with params and return the id 117 func (db *PostgresqlAdapter) Insert(sql string, args ...interface{}) (id int64, err error) { 118 119 // TODO - handle different types of id, not just int 120 // Execute the sql using db and retrieve new row id 121 row := db.sqlDB.QueryRow(sql, args...) 122 err = row.Scan(&id) 123 return id, err 124 }