-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from Paperchain/overhaul
Overhaul
- Loading branch information
Showing
11 changed files
with
957 additions
and
898 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package papergres | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"net/url" | ||
"sort" | ||
"strings" | ||
) | ||
|
||
// SSLMode defines all possible SSL options | ||
type SSLMode string | ||
|
||
const ( | ||
// SSLDisable - No SSL | ||
SSLDisable SSLMode = "disable" | ||
// SSLRequire - Always SSL, no verification | ||
SSLRequire SSLMode = "require" | ||
// SSLVerifyCA - Always SSL, verifies that certificate was signed by trusted CA | ||
SSLVerifyCA SSLMode = "verify-ca" | ||
// SSLVerifyFull - Always SSL, verifies that certificate was signed by trusted CA | ||
// and server host name matches the one in the certificate | ||
SSLVerifyFull SSLMode = "verify-full" | ||
) | ||
|
||
// Connection holds all database connection configuration. | ||
type Connection struct { | ||
Database string | ||
User string | ||
Password string | ||
Host string | ||
Port string | ||
AppName string | ||
Timeout int | ||
SSLMode SSLMode | ||
SSLCert string | ||
SSLKey string | ||
SSLRootCert string | ||
} | ||
|
||
// NewConnection creates and returns the Connection object to the postgres server | ||
func NewConnection(databaseURL string, appName string) Connection { | ||
u, err := url.Parse(databaseURL) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
host, port, _ := net.SplitHostPort(u.Host) | ||
p, _ := u.User.Password() | ||
q, _ := url.ParseQuery(u.RawQuery) | ||
path := u.Path | ||
if strings.Index(path, "/") == 0 { | ||
path = path[1:] | ||
} | ||
|
||
// Set sslmode | ||
sslMode := setSSLMode(q) | ||
|
||
// Build the Connection object | ||
conn := Connection{ | ||
User: u.User.Username(), | ||
Password: p, | ||
Host: host, | ||
Port: port, | ||
Database: path, | ||
AppName: appName, | ||
SSLMode: sslMode, | ||
} | ||
|
||
return conn | ||
} | ||
|
||
// String method builds a DSN(Data Source Name) connection string based on the | ||
// given database connection settings and returns it. | ||
func (conn *Connection) String() string { | ||
var s string | ||
if conn.Database != "" { | ||
s += fmt.Sprintf("dbname=%s ", conn.Database) | ||
} | ||
if conn.User != "" { | ||
s += fmt.Sprintf("user=%s ", conn.User) | ||
} | ||
if conn.Password != "" { | ||
s += fmt.Sprintf("password=%s ", conn.Password) | ||
} | ||
if conn.Host != "" { | ||
s += fmt.Sprintf("host=%s ", conn.Host) | ||
} | ||
if conn.Port != "" { | ||
s += fmt.Sprintf("port=%s ", conn.Port) | ||
} | ||
if conn.AppName != "" { | ||
s += fmt.Sprintf("fallback_application_name=%s ", conn.AppName) | ||
} | ||
if conn.SSLMode != "" { | ||
s += fmt.Sprintf("sslmode=%s ", conn.SSLMode) | ||
} | ||
if conn.SSLCert != "" { | ||
s += fmt.Sprintf("sslcert=%s ", conn.SSLCert) | ||
} | ||
if conn.SSLKey != "" { | ||
s += fmt.Sprintf("sslkey=%s ", conn.SSLKey) | ||
} | ||
if conn.SSLRootCert != "" { | ||
s += fmt.Sprintf("sslrootcert=%s ", conn.SSLRootCert) | ||
} | ||
s += fmt.Sprintf("connect_timeout=%v ", conn.Timeout) | ||
return s | ||
} | ||
|
||
// NewDatabase creates a new Database object | ||
func (conn Connection) NewDatabase() *Database { | ||
return &Database{ | ||
conn: &conn, | ||
} | ||
} | ||
|
||
// function to set SSL mode for connection based on url.Values | ||
func setSSLMode(q url.Values) SSLMode { | ||
sslMode := SSLDisable | ||
|
||
if len(q["sslmode"]) > 0 && q["sslmode"][0] != "" { | ||
sslMode = SSLMode(q["sslmode"][0]) | ||
} | ||
|
||
return sslMode | ||
} | ||
|
||
// prettifyConnString prints out all the props from connection string in a neat | ||
// way. | ||
func prettifyConnString(conn string) string { | ||
var str string | ||
props := strings.Split(conn, " ") | ||
sort.Strings(props) | ||
for _, s := range props { | ||
if s != "" { | ||
str += fmt.Sprintf("\n\t%s", s) | ||
} | ||
} | ||
return str | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package papergres | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
) | ||
|
||
// Database contains all required database attributes | ||
type Database struct { | ||
// conn is all information needed to connect to the database. | ||
conn *Connection | ||
|
||
// connString referes to the DSN string for the current DB. | ||
connString string | ||
} | ||
|
||
// Connection returns the connection information for a database | ||
func (db *Database) Connection() Connection { | ||
return *db.conn | ||
} | ||
|
||
// ConnectionString returns the DSN(Data Source Name) connection string for the | ||
// current DB connection. | ||
func (db *Database) ConnectionString() string { | ||
if db.connString != "" { | ||
return db.connString | ||
} | ||
db.connString = db.conn.String() | ||
return db.connString | ||
} | ||
|
||
// CreateDatabase creates a default database | ||
// Good for use during testing and local dev | ||
func (db *Database) CreateDatabase() *Result { | ||
// if Ping works then DB already exists | ||
err := db.Ping() | ||
if err == nil { | ||
return NewResult() | ||
} | ||
|
||
sql := fmt.Sprintf(` | ||
CREATE DATABASE %s | ||
WITH | ||
OWNER = postgres | ||
ENCODING = 'UTF8' | ||
LC_COLLATE = 'English_United States.1252' | ||
LC_CTYPE = 'English_United States.1252' | ||
TABLESPACE = pg_default | ||
CONNECTION LIMIT = -1;`, db.Connection().Database) | ||
|
||
conn := db.Connection() | ||
conn.Database = "" | ||
db.conn = &conn | ||
db.connString = "" | ||
return db.Query(sql).ExecNonQuery() | ||
} | ||
|
||
// GenerateInsert generates an insert query for the given object | ||
func (db *Database) GenerateInsert(obj interface{}) *Query { | ||
return db.Schema("public").GenerateInsert(obj) | ||
} | ||
|
||
// Insert inserts the passed in object | ||
func (db *Database) Insert(obj interface{}) *Result { | ||
return db.Schema("public").Insert(obj) | ||
} | ||
|
||
// InsertAll inserts a slice of objects concurrently. | ||
// objs must be a slice with items in it. | ||
// the Result slice will be in the same order as objs | ||
// so a simple loop will set all the primary keys if needed: | ||
// for i, r := range results { | ||
// objs[i].Id = r.LastInsertId.ID | ||
// } | ||
func (db *Database) InsertAll(objs interface{}) ([]*Result, error) { | ||
return db.Schema("public").InsertAll(objs) | ||
} | ||
|
||
// Ping tests the database connection | ||
func (db *Database) Ping() error { | ||
return open(db.ConnectionString()).Ping() | ||
} | ||
|
||
// Query creates a base new query object that can be used for all database operations | ||
func (db *Database) Query(sql string, args ...interface{}) *Query { | ||
return &Query{ | ||
SQL: sql, | ||
Database: db, | ||
Args: args, | ||
} | ||
} | ||
|
||
// Stats returns DBStats. Right now this only returns OpenConnections | ||
func (db *Database) Stats() sql.DBStats { | ||
return open(db.ConnectionString()).Stats() | ||
} | ||
|
||
// Schema allows for certain operations that require a specific schema | ||
func (db *Database) Schema(name string) *Schema { | ||
return &Schema{ | ||
Name: name, | ||
Database: db, | ||
} | ||
} |
Oops, something went wrong.