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  }