Skip to content

Instantly share code, notes, and snippets.

@josephspurrier
Last active January 15, 2016 12:44
Show Gist options
  • Save josephspurrier/7742f8e863ee46dd12ba to your computer and use it in GitHub Desktop.
Save josephspurrier/7742f8e863ee46dd12ba to your computer and use it in GitHub Desktop.
{
"Database": {
...
"MongoDB": {
"URL": "127.0.0.1",
"Database": "gowebapp"
}
},
...
}
package database
import (
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
"gopkg.in/mgo.v2"
)
var (
Sql *sqlx.DB // SQL wrapper
Mongo *mgo.Session // Mongo wrapper
databases DatabaseInfo // Database info
)
type DatabaseType string
const (
TypeMySQL DatabaseType = "MySQL"
TypeSQLite DatabaseType = "SQLite"
TypeMongoDB DatabaseType = "MongoDB"
)
type DatabaseInfo struct {
Type DatabaseType
MySQL MySQLInfo
SQLite SQLiteInfo
MongoDB MongoDBInfo
}
// MySQLInfo is the details for the database connection
type MySQLInfo struct {
Username string
Password string
Name string
Hostname string
Port int
Parameter string
}
// SQLiteInfo is the details for the database connection
type SQLiteInfo struct {
Parameter string
}
// MongoDBInfo is the details for the database connection
type MongoDBInfo struct {
URL string
Database string
}
// DSN returns the Data Source Name
func DSN(ci MySQLInfo) string {
// Example: root:@tcp(localhost:3306)/test
return ci.Username +
":" +
ci.Password +
"@tcp(" +
ci.Hostname +
":" +
fmt.Sprintf("%d", ci.Port) +
")/" +
ci.Name + ci.Parameter
}
// Connect to the database
func Connect(d DatabaseInfo) {
var err error
// Store the config
databases = d
switch d.Type {
case TypeMySQL:
// Connect to MySQL
if Sql, err = sqlx.Connect("mysql", DSN(d.MySQL)); err != nil {
log.Println("MySQL Driver Error", err)
}
// Check if is alive
if err = Sql.Ping(); err != nil {
log.Println("Database Error", err)
}
case TypeSQLite:
// Connect to SQLite
if Sql, err = sqlx.Connect("sqlite3", d.SQLite.Parameter); err != nil {
log.Println("SQLite Driver Error", err)
}
// Check if is alive
if err = Sql.Ping(); err != nil {
log.Println("Database Error", err)
}
case TypeMongoDB:
// Connect to MongoDB
if Mongo, err = mgo.DialWithTimeout(d.MongoDB.URL, 5); err != nil {
log.Println("MongoDB Driver Error", err)
return
}
// Prevents these errors: read tcp 127.0.0.1:27017: i/o timeout
Mongo.SetSocketTimeout(1 * time.Second)
// Check if is alive
if err = Mongo.Ping(); err != nil {
log.Println("Database Error", err)
}
default:
log.Println("No registered database in config")
}
}
// CheckConnection returns true if MongoDB is available
func CheckConnection() bool {
if Mongo == nil {
Connect(databases)
}
if Mongo != nil {
return true
}
return false
}
// ReadConfig returns the database information
func ReadConfig() DatabaseInfo {
return databases
}
package model
import (
"database/sql"
"errors"
"fmt"
"time"
"github.com/josephspurrier/gowebapp/shared/database"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// *****************************************************************************
// User
// *****************************************************************************
// User table contains the information for each user
type User struct {
objectId bson.ObjectId `bson:"_id"`
id uint32 `db:"id" bson:"id,omitempty"`
First_name string `db:"first_name" bson:"first_name"`
Last_name string `db:"last_name" bson:"last_name"`
Email string `db:"email" bson:"email"`
Password string `db:"password" bson:"password"`
Status_id uint8 `db:"status_id" bson:"status_id"`
Created_at time.Time `db:"created_at" bson:"created_at"`
Updated_at time.Time `db:"updated_at" bson:"updated_at"`
Deleted uint8 `db:"deleted" bson:"deleted"`
}
func (u *User) Id() string {
r := ""
switch database.ReadConfig().Type {
case database.TypeMySQL, database.TypeSQLite:
r = fmt.Sprintf("%v", u.id)
case database.TypeMongoDB:
r = u.objectId.Hex()
}
return r
}
// User_status table contains every possible user status (active/inactive)
type User_status struct {
Id uint8 `db:"id" bson:"id"`
Status string `db:"status" bson:"status"`
Created_at time.Time `db:"created_at" bson:"created_at"`
Updated_at time.Time `db:"updated_at" bson:"updated_at"`
Deleted uint8 `db:"deleted" bson:"deleted"`
}
var (
ErrCode = errors.New("Case statement in code is not correct.")
ErrNoResult = errors.New("Result not found.")
ErrUnavailable = errors.New("Database is unavailable.")
)
func standardizeError(err error) error {
if err == sql.ErrNoRows || err == mgo.ErrNotFound {
return ErrNoResult
}
return err
}
// UserByEmail gets user information from email
func UserByEmail(email string) (User, error) {
var err error
result := User{}
switch database.ReadConfig().Type {
case database.TypeMySQL, database.TypeSQLite:
err = database.Sql.Get(&result, "SELECT id, password, status_id, first_name FROM user WHERE email = ? LIMIT 1", email)
case database.TypeMongoDB:
if database.CheckConnection() {
session := database.Mongo.Copy()
defer session.Close()
c := session.DB(database.ReadConfig().MongoDB.Database).C("user")
err = c.Find(bson.M{"email": email}).One(&result)
} else {
err = ErrUnavailable
}
default:
err = ErrCode
}
return result, standardizeError(err)
}
// UserCreate creates user
func UserCreate(first_name, last_name, email, password string) error {
var err error
switch database.ReadConfig().Type {
case database.TypeMySQL, database.TypeSQLite:
_, err = database.Sql.Exec("INSERT INTO user (first_name, last_name, email, password) VALUES (?,?,?,?)", first_name,
last_name, email, password)
case database.TypeMongoDB:
if database.CheckConnection() {
session := database.Mongo.Copy()
defer session.Close()
c := session.DB(database.ReadConfig().MongoDB.Database).C("user")
err = c.Insert(&User{objectId: bson.NewObjectId(), First_name: first_name, Last_name: last_name, Email: email,
Password: password, Status_id: 1, Created_at: time.Now(), Updated_at: time.Now()})
} else {
err = ErrUnavailable
}
default:
err = ErrCode
}
return standardizeError(err)
}
@josephspurrier
Copy link
Author

These code changes allow you to use MongoDB with GoWebApp: https://github.com/josephspurrier/gowebapp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment