Documentation ¶
Overview ¶
Package ngorm i a Go Object relation mapper that focus on performance, maintainability, modularity, battle testing, extensibility , safety and developer frindliness.
To achieve all of the goals, the project is divided into many components. The components are desined in a functional style API, whereby objects are explicitly passed around as arguments to functions that operate on them.
This tries to avoid defining methods on structs. This comes at a cost of limiting chaining, this cost is intentional. I intend to work really hard on improving performance and thus avoiding spaghetti is not an option.
Installation ¶
You can install with go get
go get -u github.com/gernest/ngorm
The package is divided into two phases, Query building and Query execution phase.
Query Building ¶
The subpackage engine exposes a structure named Engine. This structure has everything necessary to build a query. Most of the functions defined in this package subpackages operate on this struct by accepting it as the first argument.
Having this as a separate layer helps fine tuning the generated querries and also it make easy to test and very that the ORM is doing the right thing. So, the generated query can be easily optimised without adding a lot of overhead.
Query execution ¶
This is s the phase where the generated sql query is executed. This phase is as generic as possible in a way that you can easily implement adoptes for non SQL database and still reap all the benefits of this package.
Table of Ccntents ¶
The following are links to packages under this project.
WARNING: You will never be touching most of these packages. They are the building block of the high level API.
[engine] https://godoc.org/github.com/gernest/ngorm/engine
This is what drives the whole project, helps with query building and provides conveinet structure to help with query execution.
[scope] https://godoc.org/github.com/gernest/ngorm/scope
Functions to help with model manipulations.
[search] https://godoc.org/github.com/gernest/ngorm/search
Functions to help with search querries building.
[hooks] https://godoc.org/github.com/gernest/ngorm/hooks
Callbacks executed by ngorm. You can easily overide and provide custom ones to suit your needs.
[logger] https://godoc.org/github.com/gernest/ngorm/logger
The logger used by ngorm for logging. It is an interface, and a reference implementation is provided.
[dialects] https://godoc.org/github.com/gernest/ngorm/dialects
Adopts to different SQL databases supported by ngorm. For now ngorm support ql .
Chaining ¶
The API supports methof chaining for a specific set of method.Be warned if you intend to chain anything don't forget to start with Begin method. This will help clear any context left after previous calls.
db.Begin().Model(User{}).AddIndex()
Example (BelongsTo) ¶
//One to many relationship db, err := Open("ql-mem", "test.db") if err != nil { log.Fatal(err) } defer func() { _ = db.Close() }() // Here one user can only have one profile. But one profile can belong // to multiple users. type Profile struct { model.Model Name string } type User struct { model.Model Profile Profile ProfileID int } _, err = db.Automigrate(&User{}, &Profile{}) if err != nil { log.Fatal(err) } u := User{ Profile: Profile{Name: "gernest"}, } // Creating the user with the Profile. The relation will // automatically be created and the user.ProfileID will be set to // the ID of hte created profile. err = db.Create(&u) if err != nil { log.Fatal(err) } fmt.Println(u.ProfileID == int(u.Profile.ID) && u.ProfileID != 0)
Output: true
Index ¶
- type DB
- func (db *DB) AddIndex(indexName string, columns ...string) (sql.Result, error)
- func (db *DB) AddIndexSQL(indexName string, columns ...string) (*model.Expr, error)
- func (db *DB) AddUniqueIndex(indexName string, columns ...string) (sql.Result, error)
- func (db *DB) Assign(attrs ...interface{}) *DB
- func (db *DB) Attrs(attrs ...interface{}) *DB
- func (db *DB) Automigrate(models ...interface{}) (sql.Result, error)
- func (db *DB) AutomigrateSQL(models ...interface{}) (*model.Expr, error)
- func (db *DB) Begin() *DB
- func (db *DB) Close() error
- func (db *DB) Count(value interface{}) error
- func (db *DB) Create(value interface{}) error
- func (db *DB) CreateSQL(value interface{}) (*model.Expr, error)
- func (db *DB) CreateTable(models ...interface{}) (sql.Result, error)
- func (db *DB) CreateTableSQL(models ...interface{}) (*model.Expr, error)
- func (db *DB) Delete(value interface{}, where ...interface{}) error
- func (db *DB) DeleteSQL(value interface{}, where ...interface{}) (*model.Expr, error)
- func (db *DB) Dialect() dialects.Dialect
- func (db *DB) DropColumn(column string) (sql.Result, error)
- func (db *DB) DropTable(models ...interface{}) (sql.Result, error)
- func (db *DB) DropTableIfExists(values ...interface{}) error
- func (db *DB) DropTableSQL(models ...interface{}) (*model.Expr, error)
- func (db *DB) ExecTx(query string, args ...interface{}) (sql.Result, error)
- func (db *DB) Find(out interface{}, where ...interface{}) error
- func (db *DB) FindSQL(out interface{}, where ...interface{}) (*model.Expr, error)
- func (db *DB) First(out interface{}, where ...interface{}) error
- func (db *DB) FirstOrCreate(out interface{}, where ...interface{}) error
- func (db *DB) FirstOrInit(out interface{}, where ...interface{}) error
- func (db *DB) FirstSQL(out interface{}, where ...interface{}) (*model.Expr, error)
- func (db *DB) Group(query string) *DB
- func (db *DB) HasTable(value interface{}) bool
- func (db *DB) Having(query string, values ...interface{}) *DB
- func (db *DB) Hooks() *hooks.Book
- func (db *DB) Joins(query string, args ...interface{}) *DB
- func (db *DB) Last(out interface{}, where ...interface{}) error
- func (db *DB) LastSQL(out interface{}, where ...interface{}) (*model.Expr, error)
- func (db *DB) Limit(limit interface{}) *DB
- func (db *DB) Model(value interface{}) *DB
- func (db *DB) ModifyColumn(column string, typ string) (sql.Result, error)
- func (db *DB) NewEngine() *engine.Engine
- func (db *DB) Not(query interface{}, args ...interface{}) *DB
- func (db *DB) Offset(offset interface{}) *DB
- func (db *DB) Omit(columns ...string) *DB
- func (db *DB) Or(query interface{}, args ...interface{}) *DB
- func (db *DB) Order(value interface{}, reorder ...bool) *DB
- func (db *DB) Pluck(column string, value interface{}) error
- func (db *DB) Preload(column string, conditions ...interface{}) *DB
- func (db *DB) RemoveIndex(indexName string) error
- func (db *DB) SQLCommon() model.SQLCommon
- func (db *DB) Save(value interface{}) error
- func (db *DB) SaveSQL(value interface{}) (*model.Expr, error)
- func (db *DB) Select(query interface{}, args ...interface{}) *DB
- func (db *DB) Set(key string, value interface{}) *DB
- func (db *DB) SingularTable(enable bool)
- func (db *DB) Table(name string) *DB
- func (db *DB) Update(attrs ...interface{}) error
- func (db *DB) UpdateColumn(attrs ...interface{}) error
- func (db *DB) UpdateColumns(values interface{}) error
- func (db *DB) UpdateSQL(attrs ...interface{}) (*model.Expr, error)
- func (db *DB) Updates(values interface{}, ignoreProtectedAttrs ...bool) error
- func (db *DB) UpdatesSQL(values interface{}, ignoreProtectedAttrs ...bool) (*model.Expr, error)
- func (db *DB) Where(query interface{}, args ...interface{}) *DB
- type DefaultOpener
- type Opener
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB provide an API for interacting with SQL databases using Go data structures.
func Open ¶
Open opens a database connection and returns *DB instance., dialect is the name of the driver that you want to use. The underlying connections are handled by database/sql package. Arguments that are accepted by database/sql Open function are valid here.
Not all databases are supported. There is still an ongoing efforts to add more databases but for now the following are the databases supported by this library,
The drivers for the libraries must be imported inside your application in the same package as you invoke this function.
Example
import _ "github.com/cznic/ql/driver" // imports ql driver
Example ¶
db, err := Open("ql-mem", "test.db") if err != nil { log.Fatal(err) } defer func() { _ = db.Close() }() fmt.Println(db.Dialect().GetName())
Output: ql-mem
func OpenWithOpener ¶
OpenWithOpener uses the opener to initialize the dialects and establish database connection. In fact Open does not do anything by itself, it just calls this function with the default Opener.
Please see Open function for details. The only difference is here you need to pass an Opener. See the Opener interface for details about what the Opener is and what it is used for.
func (*DB) AddIndexSQL ¶
AddIndexSQL generates SQL to add index for columns with given name
func (*DB) AddUniqueIndex ¶
AddUniqueIndex add unique index for columns with given name
func (*DB) Automigrate ¶
Automigrate creates tables that map to models if the tables don't exist yet in the database. This also takes care of situation where the models's fields have been updated(changed)
Example ¶
db, err := Open("ql-mem", "test.db") if err != nil { log.Fatal(err) } defer func() { _ = db.Close() }() type Bar struct { ID int64 Say string } type Bun struct { ID int64 Dead bool } _, err = db.Automigrate(&Bar{}, &Bun{}) if err != nil { log.Fatal(err) } var names []string qdb := db.SQLCommon() rows, err := qdb.Query("select Name from __Table ") if err != nil { log.Fatal(err) } defer func() { _ = rows.Close() }() for rows.Next() { var n string err = rows.Scan(&n) if err != nil { log.Fatal(err) fmt.Println(err) } names = append(names, n) } if err := rows.Err(); err != nil { log.Fatal(err) } sort.Strings(names) for _, v := range names { fmt.Println(v) }
Output: bars buns
func (*DB) AutomigrateSQL ¶
AutomigrateSQL generates sql query for running migrations on models.
Example ¶
db, err := Open("ql-mem", "test.db") if err != nil { log.Fatal(err) } defer func() { _ = db.Close() }() type Bar struct { ID int64 Say string } type Bun struct { ID int64 Dead bool } sql, err := db.AutomigrateSQL(&Bar{}, &Bun{}) if err != nil { log.Fatal(err) } fmt.Println(sql.Q)
Output: BEGIN TRANSACTION; CREATE TABLE bars (id int64,say string ) ; CREATE TABLE buns (id int64,dead bool ) ; COMMIT;
func (*DB) Begin ¶
Begin gives back a fresh copy of DB ready for chaining methods that operates on the same model..
func (*DB) Close ¶
Close closes the database connection and sends Done signal across all goroutines that subscribed to this instance context.
func (*DB) Create ¶
Create creates a new record.
You can hijack the execution of the generated SQL by overiding model.HookCreateExec hook.
func (*DB) CreateSQL ¶
CreateSQL generates SQl query for creating a new record/records for value. This uses Hooks to allow more flexibility.
There is no error propagation. Each step/hook execution must pass. Any error indicate the end of the execution.
The hooks that are used here are all defined in model package as constants. You can easily overide them by using DB.SetCreateHook method.
model.BeforeCreate
If set, this is the first hook to be executed. The default hook that is used is defined in hooks.BeforeCreate. If by any chance the hook returns an error then execution is halted and the error is returned.
model.HookSaveBeforeAss
If the model value has association and this is set then it will be executed. This is useful if you also want to save associations.
model.HookUpdateTimestamp
New record needs to have CreatedAt and UpdatedAt properly set. This is excuted to update the record timestamps( The default hook for this assumes you used model.Model convention for naming the timestamp fields).
model.Create
The last hook to be executed.
NOTE: All the hooks must be tailored towards generating SQL not executing anything that might change the state of the table.
All the other hooks apart from model.Create should write SQQL gerries in e.Scope.Epxrs only model.Create hook should write to e.Scope.SQL.
The end query is wrapped under TRANSACTION block.
Example ¶
db, err := Open("ql-mem", "test.db") if err != nil { log.Fatal(err) } defer func() { _ = db.Close() }() type Bar struct { ID int64 Say string } b := Bar{Say: "hello"} sql, err := db.CreateSQL(&b) if err != nil { log.Fatal(err) } fmt.Println(sql.Q) fmt.Printf("$1=%v", sql.Args[0])
Output: BEGIN TRANSACTION; INSERT INTO bars (say) VALUES ($1); COMMIT; $1=hello
Example (ExtraOptions) ¶
db, err := Open("ql-mem", "test.db") if err != nil { log.Fatal(err) } defer func() { _ = db.Close() }() type Bar struct { ID int64 Say string } b := Bar{Say: "hello"} sql, err := db.Set(model.InsertOptions, "ON CONFLICT"). CreateSQL(&b) if err != nil { log.Fatal(err) } fmt.Println(sql.Q) fmt.Printf("$1=%v", sql.Args[0])
Output: BEGIN TRANSACTION; INSERT INTO bars (say) VALUES ($1) ON CONFLICT; COMMIT; $1=hello
func (*DB) CreateTable ¶
CreateTable creates new database tables that maps to the models.
func (*DB) CreateTableSQL ¶
CreateTableSQL return the sql query for creating tables for all the given models. The queries are wrapped in a TRANSACTION block.
func (*DB) Delete ¶
Delete delete value match given conditions, if the value has primary key, then will including the primary key as condition
func (*DB) DeleteSQL ¶
DeleteSQL generates SQL to delete value match given conditions, if the value has primary key, then will including the primary key as condition
func (*DB) DropColumn ¶
DropColumn drop a column
func (*DB) DropTable ¶
DropTable drops tables that are mapped to models. You can also pass the name of the table as astring and it will be handled.
func (*DB) DropTableIfExists ¶
DropTableIfExists drop table if it is exist
func (*DB) DropTableSQL ¶
DropTableSQL generates sql query for DROP TABLE. The generated query is wrapped under TRANSACTION block.
func (*DB) ExecTx ¶
ExecTx wraps the query execution in a Transaction. This ensure all operations are Rolled back in case the execution fials.
func (*DB) First ¶
First fets the first record and order by primary key.
BUG: For some reason the ql database doesnt order the keys in ascending order. So this uses DESC to get the real record instead of ASC , I will need to dig more and see.
func (*DB) FirstOrCreate ¶
FirstOrCreate find first matched record or create a new one with given conditions (only works with struct, map conditions)
func (*DB) FirstOrInit ¶
FirstOrInit find first matched record or initialize a new one with given conditions (only works with struct, map conditions) https://jinzhu.github.io/gorm/curd.html#firstorinit
func (*DB) FirstSQL ¶
FirstSQL returns SQL query for retrieving the first record ordering by primary key.
func (*DB) HasTable ¶
HasTable returns true if there is a table for the given value, the value can either be a string representing a table name or a ngorm model.
func (*DB) Last ¶
Last finds the last record and order by primary key.
BUG: For some reason the ql database doesnt order the keys in descending order despite the use of DESC, so this uses ASC but the keys are in descending order. order. So this uses DESC to get the real record instead of ASC , I will need
func (*DB) LastSQL ¶
LastSQL returns SQL query for retrieving the last record ordering by primary key.
func (*DB) Model ¶
Model sets value as the database model. This model will be used for future calls on the erturned DB e.g
db.Model(&user).Update("name","hero")
func (*DB) ModifyColumn ¶
ModifyColumn modify column to type
func (*DB) Offset ¶
Offset specify the number of records to skip before starting to return the records
func (*DB) Omit ¶
Omit specify fields that you want to ignore when saving to database for creating, updating
func (*DB) Order ¶
Order specify order when retrieve records from database, set reorder to `true` to overwrite defined conditions
db.Order("name DESC") db.Order("name DESC", true) // reorder db.Order(gorm.Expr("name = ? DESC", "first")) // sql expression
func (*DB) Pluck ¶
Pluck used to query single column from a model as a map
var ages []int64 db.Find(&users).Pluck("age", &ages)
func (*DB) Preload ¶
Preload preload associations with given conditions
db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
func (*DB) RemoveIndex ¶
RemoveIndex remove index with name
func (*DB) Save ¶
Save update value in database, if the value doesn't have primary key, will insert it
func (*DB) SaveSQL ¶
SaveSQL generates SQL query for saving/updating database record for value.
Example ¶
db, err := Open("ql-mem", "test.db") if err != nil { log.Fatal(err) } defer func() { _ = db.Close() }() type Foo struct { ID int64 Stuff string } f := Foo{ID: 10, Stuff: "twenty"} sql, err := db.SaveSQL(&f) if err != nil { log.Fatal(err) } fmt.Println(sql.Q) fmt.Printf("$1=%v\n", sql.Args[0]) fmt.Printf("$2=%v", sql.Args[1])
Output: BEGIN TRANSACTION; UPDATE foos SET stuff = $1 WHERE id = $2; COMMIT; $1=twenty $2=10
func (*DB) Select ¶
Select specify fields that you want to retrieve from database when querying, by default, will select all fields; When creating/updating, specify fields that you want to save to database
func (*DB) SingularTable ¶
SingularTable enables or diables singular tables name. By default this is diables, meaning table names are in plurar.
Model | Plural table name ---------------------------- Session | sessions User | users Model | Singular table name ---------------------------- Session | session User | user
func (*DB) UpdateColumn ¶
UpdateColumn update attributes without callbacks
func (*DB) UpdateColumns ¶
UpdateColumns update attributes without
func (*DB) UpdateSQL ¶
UpdateSQL generates SQL that will be executed when you use db.Update
Example ¶
db, err := Open("ql-mem", "test.db") if err != nil { log.Fatal(err) } defer func() { _ = db.Close() }() type Foo struct { ID int64 Stuff string } f := Foo{ID: 10, Stuff: "twenty"} sql, err := db.Model(&f).UpdateSQL("stuff", "hello") if err != nil { log.Fatal(err) } fmt.Println(sql.Q) fmt.Printf("$1=%v\n", sql.Args[0]) fmt.Printf("$2=%v", sql.Args[1])
Output: BEGIN TRANSACTION; UPDATE foos SET stuff = $1 WHERE id = $2; COMMIT; $1=hello $2=10
func (*DB) UpdatesSQL ¶
UpdatesSQL generates sql that will be used when you run db.UpdatesSQL
Directories ¶
Path | Synopsis |
---|---|
Package builder contains functions for SQL building.
|
Package builder contains functions for SQL building. |
Package dialects defines a uniform interface for creating custom support for different SQL databases.
|
Package dialects defines a uniform interface for creating custom support for different SQL databases. |
ql
Package ql exposes implementations and functions that enables ngorm to work with ql database.
|
Package ql exposes implementations and functions that enables ngorm to work with ql database. |
Package engine defines the core structure that drives the ngorm API.
|
Package engine defines the core structure that drives the ngorm API. |
Package fixture contains all stuctures neesessary for consinstent testing on a wide range of SQL database dialects.
|
Package fixture contains all stuctures neesessary for consinstent testing on a wide range of SQL database dialects. |
Package hooks contains callbacks/hooks used by ngorm.
|
Package hooks contains callbacks/hooks used by ngorm. |
Package logger defines interface for logging and provide a reference implementation.
|
Package logger defines interface for logging and provide a reference implementation. |
Package model defines structures that are shared through out ngorm.
|
Package model defines structures that are shared through out ngorm. |
Package regexes exposes pre compiled reqular expressions that are used by ngorm.
|
Package regexes exposes pre compiled reqular expressions that are used by ngorm. |
Package scope defines functions that operates on engine.Engine and enables operating on model values easily.
|
Package scope defines functions that operates on engine.Engine and enables operating on model values easily. |
Package search contains search functions for ngorm.
|
Package search contains search functions for ngorm. |
Package util contains utility functions that are used in dirrent places of the codebase.
|
Package util contains utility functions that are used in dirrent places of the codebase. |