mirror of https://github.com/go-gorm/gorm.git
Update README
This commit is contained in:
parent
bf1db1534e
commit
094a546815
39
README.md
39
README.md
|
@ -12,41 +12,51 @@ Yet Another ORM library for Go, aims for developer friendly
|
|||
* Transaction
|
||||
* Logger Support
|
||||
* Bind struct with tag
|
||||
* Iteration Support via sql.Rows
|
||||
* sql.Scanner
|
||||
* Every feature comes with tests
|
||||
* Convention Over Configuration
|
||||
* Developer Friendly
|
||||
|
||||
## Conventions
|
||||
|
||||
* Table name is the plural of struct name's snake case.
|
||||
Disable pluralization with `db.SingularTable(true)`, or [specify your table name](#specify-table-name)
|
||||
* Column name is the snake case of field's name.
|
||||
* Use `Id int64` field as primary key.
|
||||
* Use tag `sql` to change field's property, change the tag name with `db.SetTagIdentifier(new_name)`.
|
||||
* Use `CreatedAt` to store record's created time if it exist.
|
||||
* Use `UpdatedAt` to store record's updated time if it exist.
|
||||
* Use `DeletedAt` to store record's deleted time if it exist. [Soft Delete](#soft-delete)
|
||||
|
||||
```go
|
||||
// TableName: `users`, gorm will pluralize struct's name as table name, you are possible to turn off this feature
|
||||
type User struct {
|
||||
Id int64 // Id: Database Primary key
|
||||
Id int64
|
||||
Birthday time.Time
|
||||
Age int64
|
||||
Name string `sql:"size:255"` // set this field's length in database
|
||||
CreatedAt time.Time // Time of record is created, will be insert automatically
|
||||
UpdatedAt time.Time // Time of record is updated, will be updated automatically
|
||||
DeletedAt time.Time // Time of record is deleted, refer `Soft Delete` for more
|
||||
Name string `sql:"size:255"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time
|
||||
|
||||
Emails []Email // Embedded structs
|
||||
BillingAddress Address // Embedded struct
|
||||
BillingAddressId sql.NullInt64 // Embedded struct BillingAddress's foreign key
|
||||
ShippingAddress Address // Embedded struct
|
||||
ShippingAddressId int64 // Embedded struct ShippingAddress's foreign key
|
||||
BillingAddressId sql.NullInt64 // BillingAddress's foreign key
|
||||
ShippingAddress Address // Another Embedded struct with same type
|
||||
ShippingAddressId int64 // ShippingAddress's foreign key
|
||||
IgnoreMe int64 `sql:"-"` // Ignore this field
|
||||
}
|
||||
|
||||
type Email struct { // TableName: `emails`
|
||||
type Email struct {
|
||||
Id int64
|
||||
UserId int64 // Foreign key for above embedded structs
|
||||
Email string `sql:"type:varchar(100);"` // Set this field's type in database
|
||||
UserId int64 // Foreign key for User
|
||||
Email string `sql:"type:varchar(100);"` // Set this field's type
|
||||
Subscribed bool
|
||||
}
|
||||
|
||||
type Address struct { // TableName: `addresses`
|
||||
type Address struct {
|
||||
Id int64
|
||||
Address1 string `sql:"not null;unique"` // Set this field as not null and unique in database
|
||||
Address1 string `sql:"not null;unique"` // Set this field as not nullable and unique in database
|
||||
Address2 string `sql:"type:varchar(100);unique"`
|
||||
Post sql.NullString `sql:not null`
|
||||
// FYI, "NOT NULL" will only works well with NullXXX Scanner, because golang will initalize a default value for most type...
|
||||
|
@ -735,7 +745,6 @@ db.Where("email = ?", "x@example.org").Attrs(User{RegisteredIp: "111.111.111.111
|
|||
```
|
||||
|
||||
## TODO
|
||||
* Rows, Row
|
||||
* Cache Stmt for performance
|
||||
* Join, Having, Group, Includes
|
||||
* Scopes, Valiations
|
||||
|
|
35
do.go
35
do.go
|
@ -341,6 +341,16 @@ func (s *Do) related(value interface{}, foreign_keys ...string) *Do {
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *Do) row() *sql.Row {
|
||||
s.prepareQuerySql()
|
||||
return s.db.db.QueryRow(s.sql, s.sqlVars...)
|
||||
}
|
||||
|
||||
func (s *Do) rows() (*sql.Rows, error) {
|
||||
s.prepareQuerySql()
|
||||
return s.db.db.Query(s.sql, s.sqlVars...)
|
||||
}
|
||||
|
||||
func (s *Do) query() *Do {
|
||||
defer s.trace(time.Now())
|
||||
var (
|
||||
|
@ -400,12 +410,8 @@ func (s *Do) query() *Do {
|
|||
|
||||
func (s *Do) count(value interface{}) *Do {
|
||||
defer s.trace(time.Now())
|
||||
|
||||
s.search = s.search.clone().selects("count(*)")
|
||||
s.prepareQuerySql()
|
||||
if !s.db.hasError() {
|
||||
s.err(s.db.db.QueryRow(s.sql, s.sqlVars...).Scan(value))
|
||||
}
|
||||
s.err(s.row().Scan(value))
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -419,18 +425,13 @@ func (s *Do) pluck(column string, value interface{}) *Do {
|
|||
return s
|
||||
}
|
||||
|
||||
s.prepareQuerySql()
|
||||
|
||||
if !s.db.hasError() {
|
||||
rows, err := s.db.db.Query(s.sql, s.sqlVars...)
|
||||
|
||||
if s.err(err) == nil {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
dest := reflect.New(dest_out.Type().Elem()).Interface()
|
||||
s.err(rows.Scan(dest))
|
||||
dest_out.Set(reflect.Append(dest_out, reflect.ValueOf(dest).Elem()))
|
||||
}
|
||||
rows, err := s.rows()
|
||||
if s.err(err) == nil {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
dest := reflect.New(dest_out.Type().Elem()).Interface()
|
||||
s.err(rows.Scan(dest))
|
||||
dest_out.Set(reflect.Append(dest_out, reflect.ValueOf(dest).Elem()))
|
||||
}
|
||||
}
|
||||
return s
|
||||
|
|
27
gorm_test.go
27
gorm_test.go
|
@ -1364,6 +1364,33 @@ func TestQueryChain(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRow(t *testing.T) {
|
||||
row := db.Table("users").Where("name = ?", "2").Select("age").Row()
|
||||
var age int64
|
||||
row.Scan(&age)
|
||||
if age != 20 {
|
||||
t.Errorf("Scan with Row")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRows(t *testing.T) {
|
||||
rows, err := db.Table("users").Where("name = ?", "3").Select("name, age").Rows()
|
||||
if err != nil {
|
||||
t.Errorf("Not error should happen, but got", err)
|
||||
}
|
||||
|
||||
count := 0
|
||||
for rows.Next() {
|
||||
var name string
|
||||
var age int64
|
||||
rows.Scan(&name, &age)
|
||||
count++
|
||||
}
|
||||
if count != 2 {
|
||||
t.Errorf("Should found two records with name 3")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGorm(b *testing.B) {
|
||||
b.N = 2000
|
||||
for x := 0; x < b.N; x++ {
|
||||
|
|
8
main.go
8
main.go
|
@ -93,6 +93,14 @@ func (s *DB) Find(out interface{}, where ...interface{}) *DB {
|
|||
return s.clone().do(out).where(where...).query().db
|
||||
}
|
||||
|
||||
func (s *DB) Row() *sql.Row {
|
||||
return s.do(s.data).row()
|
||||
}
|
||||
|
||||
func (s *DB) Rows() (*sql.Rows, error) {
|
||||
return s.do(s.data).rows()
|
||||
}
|
||||
|
||||
func (s *DB) Attrs(attrs ...interface{}) *DB {
|
||||
return s.clone().search.attrs(attrs...).db
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue