Newer
Older
José Carlos Nieto
committed
/*
Copyright (c) 2012-2013 José Carlos Nieto, http://xiam.menteslibres.org/
José Carlos Nieto
committed
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
Carlos Nieto
committed
menteslibres.net/db wraps third party database drivers in an attempt to make
permanent storage with Go as easy as possible. The package features a common,
consistent layer that allows executing operations against different kinds of
databases using Go expressions, without the need for explicit database-specific
instructions.
José Carlos Nieto
committed
package db
import (
"fmt"
José Carlos Nieto
committed
"reflect"
)
Carlos Nieto
committed
The db.Cond{} expression is used to filter results in a query, it can be
viewed as a replacement for the SQL "WHERE" clause.
Carlos Nieto
committed
db.Cond { "age": 18 } // Where age equals 18.
Carlos Nieto
committed
db.Cond { "age >=": 18 } // Where age is greater than or equal to 18.
Carlos Nieto
committed
db.Cond { "age $lt": 18 } // Where age is lower than 18 (MongoDB specific).
Carlos Nieto
committed
The db.And() expression is used to glue two or more expressions under logical
conjunction, it accepts db.Cond{}, db.Or() and other db.And() expressions.
Carlos Nieto
committed
Examples:
db.And (
db.Cond { "name": "Peter" },
db.Cond { "last_name": "Parker "},
)
db.And (
Carlos Nieto
committed
db.Or (
db.Cond{ "name": "Peter" },
db.Cond{ "name": "Mickey" },
Carlos Nieto
committed
),
José Carlos Nieto
committed
type And []interface{}
Carlos Nieto
committed
The db.Or() expression is used to glue two or more expressions under logical
disjunction, it accepts db.Cond{}, db.And() and other db.Or() expressions.
Example:
db.Or (
db.Cond { "year": 2012 },
db.Cond { "year": 1987 },
)
*/
José Carlos Nieto
committed
type Or []interface{}
Carlos Nieto
committed
The db.Sort expression determines how results will be sorted.
Carlos Nieto
committed
Examples:
Carlos Nieto
committed
db.Sort { "age": -1 } // Order by age, descendent.
db.Sort { "age": 1 } // Order by age, ascendent.
Carlos Nieto
committed
The db.Limit() expression sets the maximum number of rows to be returned in a
query.
Carlos Nieto
committed
If no db.Limit() is specified, all rows will be returned.
José Carlos Nieto
committed
type Limit uint
Carlos Nieto
committed
The db.Offset() expression sets the number of rows to be skipped from a
result.
Carlos Nieto
committed
If no db.Offset() is specified, no rows will be skipped.
José Carlos Nieto
committed
type Offset uint
Carlos Nieto
committed
The db.Set{} expression is used in *db.Collection.Update()*, it defines new
values for the given fields.
Example:
db.Set {
"name": "New Name",
}
*/
José Carlos Nieto
committed
Carlos Nieto
committed
// A result ID.
type Id interface{}
// Connection and authentication data.
Carlos Nieto
committed
type Settings struct {
// Host to connect to. Cannot be used if Socket is specified.
Host string
// Port to connect to. Cannot be used if Socket is specified.
Port int
// Name of the database to use.
// Authentication user name.
User string
// Authentication password.
// A path of a UNIX socket. Cannot be user if Host is specified.
Socket string
// Charset of the database.
Charset string
José Carlos Nieto
committed
}
Carlos Nieto
committed
// Returns the underlying driver the wrapper uses as an interface{}, so you
// can still use database-specific features when you need it.
José Carlos Nieto
committed
Driver() interface{}
Carlos Nieto
committed
// Attempts to open a connection using the current settings.
José Carlos Nieto
committed
Open() error
Carlos Nieto
committed
// Closes the currently active connection to the database.
José Carlos Nieto
committed
Close() error
Carlos Nieto
committed
// Returns a db.Collection struct by name.
Collection(string) (Collection, error)
Carlos Nieto
committed
// Returns the names of all the collections within the active database.
Collections() ([]string, error)
// Changes the active database.
Carlos Nieto
committed
// Drops the active database.
Carlos Nieto
committed
// Sets database connection settings.
Setup(Settings) error
Carlos Nieto
committed
// Returns the string name of the active database.
Carlos Nieto
committed
// Starts a transaction block (if the database supports transactions).
Carlos Nieto
committed
// Ends a transaction block (if the database supports transactions).
José Carlos Nieto
committed
type Collection interface {
Carlos Nieto
committed
// Inserts a new item into the collection. Can work with maps or structs.
Append(interface{}) (Id, error)
Carlos Nieto
committed
// Returns true if the collection exists.
Exists() bool
José Carlos Nieto
committed
Carlos Nieto
committed
// Creates a filter with the given conditions and returns a result set.
Filter(...interface{}) (Result, error)
José Carlos Nieto
committed
Carlos Nieto
committed
// Truncates the collection.
Truncate() error
Carlos Nieto
committed
// Returns the string name of the collection.
José Carlos Nieto
committed
}
José Carlos Nieto
committed
// Result methods.
type Result interface {
Carlos Nieto
committed
// Removes all items within the result set.
Carlos Nieto
committed
// Updates all items within the result set.
Carlos Nieto
committed
// Counts all items within the result set.
Carlos Nieto
committed
// Fetches all the results of the query into the given pointer.
//
// Accepts a pointer to slice of maps or structs.
All(interface{}) error
Carlos Nieto
committed
// Fetches the first result of the query into the given pointer and discards
// the rest.
//
// Accepts a pointer to map or struct.
One(interface{}) error
Carlos Nieto
committed
// Fetches the next result of the query into the given pointer. Returns error if
// there are no more results.
// Warning: If you're only using part of these results you must manually Close()
// the result.
//
// Accepts a pointer to map or struct.
José Carlos Nieto
committed
Next(interface{}) error
Carlos Nieto
committed
// Closes the resultset.
José Carlos Nieto
committed
Close() error
}
// Specifies which fields will be returned in a query.
Carlos Nieto
committed
//type MultiFlag bool
//type SqlValues []string
//type SqlArgs []string
// Error messages
var (
ErrExpectingPointer = errors.New(`Expecting a pointer destination (dst interface{}).`)
ErrExpectingSlicePointer = errors.New(`Expecting a pointer to an slice (dst interface{}).`)
ErrExpectingSliceMapStruct = errors.New(`Expecting a pointer to an slice of maps or structs (dst interface{}).`)
ErrExpectingMapOrStruct = errors.New(`Expecting either a pointer to a map or a pointer to a struct.`)
ErrNoMoreRows = errors.New(`There are no more rows in this result set.`)
ErrNotConnected = errors.New(`You're currently not connected.`)
ErrMissingDatabaseName = errors.New(`Missing a database name.`)
ErrCollectionDoesNotExists = errors.New(`Collection does not exists.`)
ErrSockerOrHost = errors.New(`You can connect either to a socket or a host but not both.`)
ErrQueryLimitParam = errors.New(`A query can accept only one db.Limit() parameter.`)
ErrQuerySortParam = errors.New(`A query can accept only one db.Sort{} parameter.`)
ErrQueryOffsetParam = errors.New(`A query can accept only one db.Offset() parameter.`)
ErrMissingConditions = errors.New(`Missing selector conditions.`)
)
var wrappers = make(map[string]Database)
Carlos Nieto
committed
// Registers a database wrapper with a unique name.
func Register(name string, driver Database) {
José Carlos Nieto
committed
if name == "" {
José Carlos Nieto
committed
if _, ok := wrappers[name]; ok != false {
José Carlos Nieto
committed
panic("Register called twice for driver " + name)
José Carlos Nieto
committed
wrappers[name] = driver
}
Carlos Nieto
committed
// Configures a connection to a database using the named wrapper and the given
// settings.
func Open(name string, settings Settings) (Database, error) {
José Carlos Nieto
committed
driver, ok := wrappers[name]
if ok == false {
panic(fmt.Sprintf("Unknown wrapper: %s.", name))
José Carlos Nieto
committed
// Creating a new connection everytime Open() is called.
Carlos Nieto
committed
t := reflect.ValueOf(driver).Elem().Type()
conn := reflect.New(t).Interface().(Database)
José Carlos Nieto
committed
Carlos Nieto
committed
// Setting up the connection with the given source.
José Carlos Nieto
committed
err := conn.Setup(settings)
if err != nil {
return nil, err
}
José Carlos Nieto
committed
return conn, nil