toyorm

package module
v0.3.1-alpha Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 11, 2018 License: MIT Imports: 13 Imported by: 3

README

Toyorm

this is powerful sql orm library for Golang, have some funny features

Build Status codecov Go Report Card GoDoc Join the chat



Support database

sqlite3 mysql postgresql

Go version

version go-1.9


A Simple Example

here


Website Example

here


Database connection

import database driver

// if database is mysql
_ "github.com/go-sql-driver/mysql"
// if database is sqlite3
_ "github.com/mattn/go-sqlite3"
// when database is postgres
_ "github.com/lib/pq"

create a toy

// if database is mysql, make sure your mysql have toyorm_example schema
toy, err = toyorm.Open("mysql", "root:@tcp(localhost:3306)/toyorm_example?charset=utf8&parseTime=True")
// if database is sqlite3
toy,err = toyorm.Open("sqlite3", "toyorm_test.db")
// when database is postgres
toy, err = toyorm.Open("postgres", "user=postgres dbname=toyorm sslmode=disable")
Model definition
example
type Extra map[string]interface{}

func (e Extra) Scan(value interface{}) error {
     switch v := value.(type) {
     case string:
          return json.Unmarshal([]byte(v), e)
     case []byte:
          return json.Unmarshal(v, e)
     default:
          return errors.New("not support type")
     }
}

func (e Extra) Value() (driver.Value, error) {
     return json.Marshal(e)
}

type UserDetail struct {
     ID       int  `toyorm:"primary key;auto_increment"`
     UserID   uint `toyorm:"index"`
     MainPage string
     Extra    Extra `toyorm:"type:VARCHAR(1024)"`
}

type Blog struct {
     toyorm.ModelDefault
     UserID  uint   `toyorm:"index"`
     Title   string `toyorm:"index"`
     Content string
}

type User struct {
     toyorm.ModelDefault
     Name    string `toyorm:"unique index"`
     Age     int
     Sex     string
     Detail  *UserDetail
     Friends []*User
     Blog    []Blog
}
type translate

if sql type is not match, toyorm will ignore it in Sql Operation

you can use <type:sql_type> field tag to specified their sql type

the following type will auto translate to sql type

Go Type sql type
bool BOOLEAN
int8,int16,int32,uint8,uint16,uint32 INTEGER
int64,uint64,int,uint BIGINT
float32,float64 FLOAT
string VARCHAR(255)
time.Time TIMESTAMP
[]byte VARCHAR(255)
sql.NullBool BOOLEAN
sql.NullInt64 BIGINT
sql.NullFloat64 FLOAT
sql.NullString VARCHAR(255)
sql.RawBytes VARCHAR(255)

special fields

  1. special fields have some process in handlers, do not try to change it type or set it value
Field Name Type Description
CreatedAt time.Time generate when element be create
UpdatedAt time.Time generate when element be update/create
DeletedAt *time.Time delete mode is soft

field tags

  1. tag format can be <key:value> or <key>

  2. the following is special tag

Key Value Description
index void or string use for optimization when search condition have this field,if you want make a combined,just set same index name with fields
unique index void or string have unique limit index, other same as index
primary key void allow multiple primary key,but some operation not support
- void ignore this field in sql
type string sql type
column string sql column name
auto_increment void recommend, if your table primary key have auto_increment attribute must add it
autoincrement void same as auto_increment
foreign key void to add foreign key feature when create table
alias string change field name with toyorm
join string to select related container field when call brick.Join

other custom TAG will append to end of CREATE TABLE field

Bind models
  1. model kind must be a struct or a point with struct

  2. the model is what information that toyorm know about the table

brick := toy.Model(&User{})
// or
brick := toy.Model(User{})
Sql Operation

create table
var err error
_, err = toy.Model(&User{}).Debug().CreateTable()
// CREATE TABLE user (id BIGINT AUTO_INCREMENT,created_at TIMESTAMP NULL,updated_at TIMESTAMP NULL,deleted_at TIMESTAMP NULL,name VARCHAR(255),age BIGINT ,sex VARCHAR(255) , PRIMARY KEY(id))
// CREATE INDEX idx_user_deletedat ON user(deleted_at)
// CREATE UNIQUE INDEX udx_user_name ON user(name)
_, err =toy.Model(&UserDetail{}).Debug().CreateTable()
// CREATE TABLE user_detail (id BIGINT AUTO_INCREMENT,user_id BIGINT,main_page Text,extra VARCHAR(1024), PRIMARY KEY(id))
// CREATE INDEX idx_user_detail_userid ON user_detail(user_id)
_, err =toy.Model(&Blog{}).Debug().CreateTable()
// CREATE TABLE blog (id BIGINT AUTO_INCREMENT,created_at TIMESTAMP NULL,updated_at TIMESTAMP NULL,deleted_at TIMESTAMP NULL,user_id BIGINT,title VARCHAR(255),content VARCHAR(255) , PRIMARY KEY(id))
// CREATE INDEX idx_blog_deletedat ON blog(deleted_at)
// CREATE INDEX idx_blog_userid ON blog(user_id)
// CREATE INDEX idx_blog_title ON blog(title)
drop table
var err error
_, err =toy.Model(&User{}).Debug().DropTable()
// DROP TABLE user
_, err =toy.Model(&UserDetail{}).Debug().DropTable()
// DROP TABLE user_detail
_, err =toy.Model(&Blog{}).Debug().DropTable()
// DROP TABLE blog
insert/save data

// insert with autoincrement will set id to source data

user := &User{
    Name: "bigpigeon",
    Age:  18,
    Sex:  "male",
}
_, err = toy.Model(&User{}).Debug().Insert(&user)
// INSERT INTO user(created_at,updated_at,name,age,sex) VALUES(?,?,?,?,?) , args:[]interface {}{time.Time{wall:0xbe8df5112e7f07c8, ext:210013499, loc:(*time.Location)(0x141af80)}, time.Time{wall:0xbe8df5112e7f1768, ext:210017044, loc:(*time.Location)(0x141af80)}, "bigpigeon", 18, "male"}
// print user format with json
/* {
  "ID": 1,
  "CreatedAt": "2018-01-11T20:47:00.780077+08:00",
  "UpdatedAt": "2018-01-11T20:47:00.780081+08:00",
  "DeletedAt": null,
  "Name": "bigpigeon",
  "Age": 18,
  "Sex": "male",
  "Detail": null,
  "Friends": null,
  "Blog": null
}*/

// save data use "REPLACE INTO" when primary key exist

users := []User{
    {
        ModelDefault: toyorm.ModelDefault{ID: 1},
        Name:         "bigpigeon",
        Age:          18,
        Sex:          "male",
    },
    {
        Name: "fatpigeon",
        Age:  27,
        Sex:  "male",
    },
}
_, err = toy.Model(&User{}).Debug().Save(&user)
// SELECT id,created_at FROM user WHERE id IN (?), args:[]interface {}{0x1}
// REPLACE INTO user(id,created_at,updated_at,name,age,sex) VALUES(?,?,?,?,?,?) , args:[]interface {}{0x1, time.Time{wall:0x0, ext:63651278036, loc:(*time.Location)(nil)}, time.Time{wall:0xbe8dfb5511465918, ext:302600558, loc:(*time.Location)(0x141af80)}, "bigpigeon", 18, "male"}
// INSERT INTO user(created_at,updated_at,name,age,sex) VALUES(?,?,?,?,?) , args:[]interface {}{time.Time{wall:0xbe8dfb551131b7d8, ext:301251230, loc:(*time.Location)(0x141af80)}, time.Time{wall:0xbe8dfb5511465918, ext:302600558, loc:(*time.Location)(0x141af80)}, "fatpigeon", 27, "male"}

update
toy.Model(&User{}).Debug().Update(&User{
    Age: 4,
})
// UPDATE user SET updated_at=?,age=? WHERE deleted_at IS NULL, args:[]interface {}{time.Time{wall:0xbe8df4eb81b6c050, ext:233425327, loc:(*time.Location)(0x141af80)}, 4}
find

find one

var user User
_, err = toy.Model(&User{}).Debug().Find(&user}
// SELECT id,created_at,updated_at,deleted_at,name,age,sex FROM user WHERE deleted_at IS NULL LIMIT 1, args:[]interface {}(nil)
// print user format with json
/* {
  "ID": 1,
  "CreatedAt": "2018-01-11T12:47:01Z",
  "UpdatedAt": "2018-01-11T12:47:01Z",
  "DeletedAt": null,
  "Name": "bigpigeon",
  "Age": 4,
  "Sex": "male",
  "Detail": null,
  "Friends": null,
  "Blog": null
}*/

find multiple

var users []User
_, err = brick.Debug().Find(&users)
fmt.Printf("find users %s\n", JsonEncode(&users))

// SELECT id,created_at,updated_at,deleted_at,name,age,sex FROM user WHERE deleted_at IS NULL, args:[]interface {}(nil)
delete

delete with primary key

_, err = brick.Debug().Delete(&user)
// UPDATE user SET deleted_at=? WHERE id IN (?), args:[]interface {}{(*time.Time)(0xc4200f0520), 0x1}

delete with condition

_, err = brick.Debug().Where(toyorm.ExprEqual, Offsetof(User{}.Name), "bigpigeon").DeleteWithConditions()
// UPDATE user SET deleted_at=? WHERE name = ?, args:[]interface {}{(*time.Time)(0xc4200dbfa0), "bigpigeon"}
ToyBrick

use toy.Model will create a ToyBrick, you need use it to build grammar and operate the database

Where condition

affective update/find/delete operation

usage

where will clean old conditions and make new one

brick.Where(<expr>, <Key>, [value])

conditions will copy conditions and clean old conditions

brick.Conditions(<toyorm.Search>)

or & and condition will use or/and to link new condition when current condition is not nil

brick.Or().Condition(<expr>, <Key>, [value])
brick.And().Condition(<expr>, <Key>, [value])

or & and conditions will use or/and to link new conditions

brick.Or().Conditions(<toyorm.Search>)
brick.And().Conditions(<toyorm.Search>)
SearchExpr
SearchExpr to sql example
ExprAnd AND brick.Where(ExprAnd, Product{Name:"food one", Count: 4}) // WHERE name = "food one" AND Count = 4
ExprOr OR brick.Where(ExprOr, Product{Name:"food one", Count: 4}) // WHERE name = "food one" OR Count = "4"
ExprEqual = brick.Where(ExprEqual, OffsetOf(Product{}.Name), "food one") // WHERE name = "find one"
ExprNotEqual <> brick.Where(ExprNotEqual, OffsetOf(Product{}.Name), "food one") // WHERE name <> "find one"
ExprGreater > brick.Where(ExprGreater, OffsetOf(Product{}.Count), 3) // WHERE count > 3
ExprGreaterEqual >= brick.Where(ExprGreaterEqual, OffsetOf(Product{}.Count), 3) // WHERE count >= 3
ExprLess < brick.Where(ExprLess, OffsetOf(Product{}.Count), 3) // WHERE count < 3
ExprLessEqual <= brick.Where(ExprLessEqual, OffsetOf(Product{}.Count), 3) // WHERE count <= 3
ExprBetween Between brick.Where(ExprBetween, OffsetOf(Product{}.Count), [2]int{2,3}) // WHERE count BETWEEN 2 AND 3
ExprNotBetween NOT Between brick.Where(ExprNotBetween, OffsetOf(Product{}.Count), [2]int{2,3}) // WHERE count NOT BETWEEN 2 AND 3
ExprIn IN brick.Where(ExprIn, OffsetOf(Product{}.Count), []int{1, 2, 3}) // WHERE count IN (1,2,3)
ExprNotIn NOT IN brick.Where(ExprNotIn, OffsetOf(Product{}.Count), []int{1, 2, 3}) // WHERE count NOT IN (1,2,3)
ExprLike LIKE brick.Where(ExprLike, OffsetOf(Product{}.Name), "one") // WHERE name LIKE "one"
ExprNotLike NOT LIKE brick.Where(ExprNotLike, OffsetOf(Product{}.Name), "one") // WHERE name NOT LIKE "one"
ExprNull IS NULL brick.Where(ExprNull, OffsetOf(Product{}.DeletedAt)) // WHERE DeletedAt IS NULL
ExprNotNull IS NOT NULL brick.Where(ExprNotNull, OffsetOf(Product{}.DeletedAt)) // WHERE DeletedAt IS NOT NULL
example

single condition

brick = brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Tag), "food")
or use string
brick = brick.Where("=", Offsetof(Product{}.Tag), "food")
// WHERE tag = "food"

combination condition

brick = brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Count), 2).And().
    Condition(toyorm.ExprGreater, Offsetof(Product{}.Price), 3).Or().
    Condition(toyorm.ExprEqual, Offsetof(Product{}.Count), 4)
or use string
brick = brick.Where("=", Offsetof(Product{}.Count), 2).And().
    Condition(">", Offsetof(Product{}.Price), 3).Or().
    Condition("=", Offsetof(Product{}.Count), 4)
// WHERE count = 2 and price > 3 or count = 4

priority condition

brick.Where(toyorm.ExprGreater, Offsetof(Product{}.Price), 3).And().Conditions(
    brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Count), 2).Or().
    Condition(toyorm.ExprEqual, Offsetof(Product{}.Count), 1).Search
)
or use string
brick.Where(">", Offsetof(Product{}.Price), 3).And().Conditions(
    brick.Where("=", Offsetof(Product{}.Count), 2).Or().
    Condition("=", Offsetof(Product{}.Count), 1).Search
)
// WHERE price > 3 and (count = 2 or count = 1)
brick.Conditions(
    brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Count), 2).Or().
        Condition(toyorm.ExprEqual, Offsetof(Product{}.Count), 1).Search,
).And().Conditions(
    brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Price), 3).Or().
        Condition(toyorm.ExprEqual, Offsetof(Product{}.Price), 4).Search,
)
or use string
brick.Conditions(
    brick.Where("=", Offsetof(Product{}.Count), 2).Or().
        Condition("=", Offsetof(Product{}.Count), 1).Search,
).And().Conditions(
    brick.Where("=", Offsetof(Product{}.Price), 3).Or().
        Condition("=", Offsetof(Product{}.Price), 4).Search,
)
// WHERE (count = ? OR count = ?) AND (price = ? OR price = ?)

limit & offset

brick := brick.Offset(2).Limit(2)
// LIMIT 2 OFFSET 2

order by

brick = brick.OrderBy(Offsetof(Product{}.Name))
// ORDER BY name

order by desc

brick = brick.OrderBy(brick.ToDesc(Offsetof(Product{}.Name)))
// ORDER BY name DESC
Transaction

start a transaction

brick = brick.Begin()

rollback all sql action

err = brick.Rollback()

commit all sql action

err = brick.Commit()
Debug

if Set debug all sql action will have log

brick = brick.Debug()
IgnoreMode

when I Update or Search with struct that have some zero value, did I update it ?

use IgnoreMode to differentiate what zero value should update

brick = brick.IgnoreMode(toyorm.Mode("Update"), toyorm.IgnoreZero ^ toyorm.IgnoreZeroLen)
// ignore all zeor value but excloud zero len slice
// now value = []int(nil) will ignore when update
// but value = []int{} will update when update

In default

Operation Mode affect
Insert IgnoreNo brick.Insert()
Replace IgnoreNo brick.Replace()
Condition IgnoreZero brick.Where(ExprAnd/ExprOr, )
Update IgnoreZero brick.Update()

All of IgnoreMode

mode effective
IgnoreFalse ignore field type is bool and value is false
IgnoreZeroInt ignore field type is int/uint/uintptr(incloud their 16,32,64 bit type) and value is 0
IgnoreZeroFloat ignore field type is float32/float64 and value is 0.0
IgnoreZeroComplex ignore field type is complex64/complex128 and value is 0 + 0i
IgnoreNilString ignore field type is string and value is ""
IgnoreNilPoint ignore field type is point/map/slice and value is nil
IgnoreZeroLen ignore field type is map/array/slice and len = 0
IgnoreNullStruct ignore field type is struct and value is zero value struct e.g type A struct{A string,B int}, A{"", 0} will be ignore
IgnoreNil ignore with IgnoreNilPoint and IgnoreZeroLen
IgnoreZero ignore all of the above
BindFields

if bind a not null fields, the IgnoreMode will failure

{
    var p Product
    result, err := brick.BindDefaultFields(Offsetof(p.Price), Offsetof(p.UpdatedAt)).Update(&Product{
        Price: 0,
    })
   // process error
   ...
}
var products []Product
result, err = brick.Find(&products)
// process error
...

for _, p := range products {
    fmt.Printf("product name %s, price %v\n", p.Name, p.Price)
}
Scope

use scope to do some custom operation

// desc all order by fields
brick.Scope(func(t *ToyBrick) *ToyBrick{

    newOrderBy := make([]*ModelFields, len(t.orderBy))
    for i, f := range t.orderBy {
        newOrderBy = append(newOrderBy, t.ToDesc(f))
    }
    newt := *t
    newt.orderBy = newOrderBy
    return &newt
})
Template

use template exec to replace default exec

now template only support Insert/Save/Update/Find

Custom insert
data := Product{
    Name:  "bag",
    Price: 9999,
    Count: 2,
    Tag:   "container",
}
result, err := brick.Template("INSERT INTO $ModelName($Columns) Values($Values)").Insert(&data)
// INSERT INTO product(created_at,updated_at,deleted_at,name,price,count,tag) Values(?,?,?,?,?,?,?) args:["2018-04-01T17:05:48.927499+08:00","2018-04-01T17:05:48.927499+08:00",null,"bag",9999,2,"container"]
Custom find
var data Product
// if driver is mysql use "USE INDEX" replace "INDEXED BY"
result, err := brick.Template("SELECT $Columns FROM $ModelName INDEXED BY idx_product_name $Conditions").
    Where("=", Offsetof(Product{}.Name), "bag").Find(&data)
// SELECT id,created_at,updated_at,deleted_at,name,price,count,tag FROM product INDEXED BY idx_product_name  WHERE deleted_at IS NULL AND name = ? LIMIT 1  args:["bag"]
Custom update

set count = count + 2

result, err := brick.Template(fmt.Sprintf("UPDATE $ModelName SET $Values,$FN-Count = $0x%x + ? $Conditions", Offsetof(Product{}.Count)), 2).
	Where("=", Offsetof(Product{}.Name), "bag").Update(&Product{Price: 200})
// UPDATE product SET updated_at = ?,price = ?,count = count + ?  WHERE deleted_at IS NULL AND name = ?  args:["2018-04-01T17:50:35.205377+08:00",200,2,"bag"]
Placeholder

follower placeholder use in template example

two special placeholder

  1. $FN- will convert struct field name to table field name e.g $FN-Name => name
  2. $0x will convert struct field offset to table field name e.g $0x58 => Count
action \ placeholder $ModelName $Columns $Values $Conditions
Find product id,data,... - WHERE ... ORDER BY ... GROUP BY ... LIMIT ... OFFSET ...
Insert product id,data,... ?,?,... WHERE ... ORDER BY ... GROUP BY ... LIMIT ... OFFSET ...
Save product id,data,... ?,?,... WHERE ... ORDER BY ... GROUP BY ... LIMIT ... OFFSET ...
Update product id,data,... id = ?,data = ?,... WHERE ... ORDER BY ... GROUP BY ... LIMIT ... OFFSET ...
Thread safe

Thread safe if you comply with the following agreement

  1. make sure ToyBrick object is read only, if you want to change it, create a new one

  2. do not use append to change ToyBrick's slice data,use make and copy to clone new slice

Preload

preload need have relation field and container field

relations field is used to link the main record and sub record

container field is used to hold sub record

Preload example

here

One to one

relation field at sub model

relation field name must be main model type name + main model primary key name

type User struct {
    toyorm.ModelDefault
    // container field
    Detail  *UserDetail
}

type UserDetail struct {
    ID       int    `toyorm:"primary key;auto_increment"`
    // relation field
    UserID   uint   `toyorm:"index"`
    MainPage string `toyorm:"type:Text"`
}

// load preload
brick = toy.Model(&User{}).Debug().Preload(OffsetOf(User.Detail)).Enter()

Belong to

relation field at main model

relation field name must be container field name + sub model primary key name

type User struct {
    toyorm.ModelDefault
    // container field
    Detail   *UserDetail
    // relation field
    DetailID int `toyorm:"index"`
}

type UserDetail struct {
    ID       int    `toyorm:"primary key;auto_increment"`
    MainPage string `toyorm:"type:Text"`
}

One to many

relation field at sub model

relation field name must be main model type name + main model primary key name

type User struct {
    toyorm.ModelDefault
    // container field
    Blog    []Blog
}

type Blog struct {
    toyorm.ModelDefault
    // relation field
    UserID  uint   `toyorm:"index"`
    Title   string `toyorm:"index"`
    Content string
}

Many to many

many to many not need to specified the relation ship,it relation field at middle model

type User struct {
    toyorm.ModelDefault
    // container field
    Friends    []*User
}
Load preload

when you finish model definition, it time to load preload

// create a main brick
brick = toy.Model(&User{})
// create a sub brick
subBrick := brick.Preload(OffsetOf(User.Blog))
// you can editing any attribute what you want, just like editing it on main model
subBrick = subBrick.Where(ExprEqual, OffsetOf(Blog.Title), "my blog")
// finished change ,use Enter() go back the main brick
brick = subBrick.Enter()

if you not like relation field name rule,use custom module to create it

// one to one custom
brick.CustomOneToOnePreload(<main container>, <sub relation>, [sub model struct])
// belong to custom
brick.CustomBelongToPreload(<main container>, <main relation>, [sub model struct])
// one to many
brick.CustomOneToManyPreload(<main container>, <sub relation>, [sub model struct])
// many to many
brick.CustomManyToManyPreload(<middle model struct>, <main container>, <main relation>, <sub relation>, [sub model struct])
Join

different association query is join query

Example

here

Model Define

use join tag to association related field/ join tag value must same as container field name

type Extra map[string]interface{}

func (e *Extra) Scan(value interface{}) error {
	switch v := value.(type) {
	case string:
		return json.Unmarshal([]byte(v), e)
	case []byte:
		return json.Unmarshal(v, e)
	default:
		return errors.New("not support type")
	}
}

func (e Extra) Value() (driver.Value, error) {
	return json.Marshal(e)
}

type Color struct {
	Name string `toyorm:"primary key;join:ColorDetail"`
	Code int32
}

type Comment struct {
	toyorm.ModelDefault
	ProductDetailProductID uint32 `toyorm:"index"`
	Data                   string `toyorm:"type:VARCHAR(1024)"`
}

type ProductDetail struct {
	ProductID  uint32 `toyorm:"primary key;join:Detail"`
	Title      string
	CustomPage string `toyorm:"type:text"`
	Extra      Extra  `toyorm:"type:VARCHAR(2048)"`
	Color      string `toyorm:"join:ColorDetail"`
	ColorJoin  Color  `toyorm:"alias:ColorDetail"`
	Comment    []Comment
}

type Product struct {
	ID        uint32     `toyorm:"primary key;auto_increment;join:Detail"`
	CreatedAt time.Time  `toyorm:"NULL"`
	DeletedAt *time.Time `toyorm:"NULL"`
	Name      string
	Count     int
	Price     float64
	Detail    *ProductDetail
}
Join in Find

Swap on Join just like Enter on Preload, can back to previous data

brick := toy.Model(&tab).Debug().
    Join(Offsetof(tab.Detail)).
    Join(Offsetof(detailTab.ColorJoin)).Swap().Swap()
var scanData []Product
result, err = brick.Find(&scanData)
// SELECT m.id,m.created_at,m.deleted_at,m.name,m.count,m.price,m_0.product_id,m_0.title,m_0.custom_page,m_0.extra,m_0.color,m_0_0.name,m_0_0.code FROM `product` as `m` JOIN `product_detail` AS `m_0` ON m.id = m_0.product_id JOIN `color` AS `m_0_0` ON m_0.color = m_0_0.name   WHERE m.deleted_at IS NULL

use Join to switch current model and add conditions

// where Product.Name = "clean stick" or Color.Name = "black"
brick := toy.Model(&tab).Debug().Where("=", Offsetof(tab.Name), "clean stick").
    Join(Offsetof(tab.Detail)).
    Join(Offsetof(detailTab.ColorJoin)).Or().Condition("=", Offsetof(colorTab.Name), "black").
    Swap().Swap()
var scanData []Product
result, err = brick.Find(&scanData)
// SELECT m.id,m.created_at,m.deleted_at,m.name,m.count,m.price,m_0.product_id,m_0.title,m_0.custom_page,m_0.extra,m_0.color,m_0_0.name,m_0_0.code FROM `product` as `m` JOIN `product_detail` AS `m_0` ON m.id = m_0.product_id JOIN `color` AS `m_0_0` ON m_0.color = m_0_0.name   WHERE m.deleted_at IS NULL AND (m.name = ? OR m_0_0.name = ?)  args:["clean stick","black"]

set order just like add conditions

// where Product.Name = "clean stick" or Color.Name = "black"
brick := toy.Model(&tab).Debug().
    Join(Offsetof(tab.Detail)).
    Join(Offsetof(detailTab.ColorJoin)).OrderBy(Offsetof(colorTab.Name)).
    Swap().Swap()
var scanData []Product
result, err = brick.Find(&scanData)
// SELECT m.id,m.created_at,m.deleted_at,m.name,m.count,m.price,m_0.product_id,m_0.title,m_0.custom_page,m_0.extra,m_0.color,m_0_0.name,m_0_0.code FROM `product` as `m` JOIN `product_detail` AS `m_0` ON m.id = m_0.product_id JOIN `color` AS `m_0_0` ON m_0.color = m_0_0.name   WHERE m.deleted_at IS NULL ORDER BY m_0_0.name

also can set GroupBy but here not example

Preload On Join

Preload method also work on Join mode

brick := toy.Model(&tab).Debug().
    Join(Offsetof(tab.Detail)).Preload(Offsetof(detailTab.Comment)).Enter().
    Join(Offsetof(detailTab.ColorJoin)).Swap().Swap()
var scanData []Product
result, err = brick.Find(&scanData)
// SELECT m.id,m.created_at,m.deleted_at,m.name,m.count,m.price,m_0.product_id,m_0.title,m_0.custom_page,m_0.extra,m_0.color,m_0_0.name,m_0_0.code FROM `product` as `m` JOIN `product_detail` AS `m_0` ON m.id = m_0.product_id JOIN `color` AS `m_0_0` ON m_0.color = m_0_0.name   WHERE m.deleted_at IS NULL
// SELECT id,created_at,updated_at,deleted_at,product_detail_product_id,data FROM `comment`   WHERE deleted_at IS NULL AND product_detail_product_id IN (?,?,?)  args:[1,2,3]
Result

use Report to view sql action

report format

insert

user := User{
    Detail: &UserDetail{
        MainPage: "some html code with you page",
        Extra:    Extra{"title": "my blog"},
    },
    Blog: []Blog{
        {Title: "how to write a blog", Content: "first ..."},
        {Title: "blog introduction", Content: "..."},
    },
    Friends: []*User{
        {
            Detail: &UserDetail{
                MainPage: "some html code with you page",
                Extra:    Extra{},
            },
            Blog: []Blog{
                {Title: "some python tech", Content: "first ..."},
                {Title: "my eleme_union_meal usage", Content: "..."},
            },
            Name: "fatpigeon",
            Age:  18,
            Sex:  "male",
        },
    },
    Name: "bigpigeon",
    Age:  18,
    Sex:  "male",
}
result, err = brick.Save(&user)
// error process ...
fmt.Printf("report:\n%s\n", result.Report())

/*
// [0, ] means affected the 0 element
// [0-0, ] means affected the 0 element the 0 sub element
report:
[0, ] INSERT INTO user(created_at,updated_at,deleted_at,name,age,sex) VALUES(?,?,?,?,?,?)  args:["2018-02-28T17:31:20.012285+08:00","2018-02-28T17:31:20.012285+08:00",null,"bigpigeon",18,"male"]
	preload Detail
	[0-, ] INSERT INTO user_detail(user_id,main_page,extra) VALUES(?,?,?)  args:[1,"some html code with you page",{"title":"my blog"}]
	preload Blog
	[0-0, ] INSERT INTO blog(created_at,updated_at,deleted_at,user_id,title,content) VALUES(?,?,?,?,?,?)  args:["2018-02-28T17:31:20.013968+08:00","2018-02-28T17:31:20.013968+08:00",null,1,"how to write a blog","first ..."]
	[0-1, ] INSERT INTO blog(created_at,updated_at,deleted_at,user_id,title,content) VALUES(?,?,?,?,?,?)  args:["2018-02-28T17:31:20.013968+08:00","2018-02-28T17:31:20.013968+08:00",null,1,"blog introduction","..."]
	preload Friends
	[0-0, ] INSERT INTO user(created_at,updated_at,deleted_at,name,age,sex) VALUES(?,?,?,?,?,?)  args:["2018-02-28T17:31:20.015207+08:00","2018-02-28T17:31:20.015207+08:00",null,"fatpigeon",18,"male"]
		preload Detail
		[0-0-, ] INSERT INTO user_detail(user_id,main_page,extra) VALUES(?,?,?)  args:[2,"some html code with you page",{}]
		preload Blog
		[0-0-0, ] INSERT INTO blog(created_at,updated_at,deleted_at,user_id,title,content) VALUES(?,?,?,?,?,?)  args:["2018-02-28T17:31:20.016389+08:00","2018-02-28T17:31:20.016389+08:00",null,2,"some python tech","first ..."]
		[0-0-1, ] INSERT INTO blog(created_at,updated_at,deleted_at,user_id,title,content) VALUES(?,?,?,?,?,?)  args:["2018-02-28T17:31:20.016389+08:00","2018-02-28T17:31:20.016389+08:00",null,2,"my eleme_union_meal usage","..."]
*/

find

brick := brick.Preload(Offsetof(User{}.Friends)).
    Preload(Offsetof(User{}.Detail)).Enter().
    Preload(Offsetof(User{}.Blog)).Enter().
    Enter()
var users []User
result, err = brick.Find(&users)
// some error process
...
// print the report
fmt.Printf("report:\n%s\n", result.Report())

// report log
/*
report:
[0, 1, ] SELECT id,created_at,updated_at,deleted_at,name,age,sex FROM user WHERE deleted_at IS NULL  args:null
	preload Detail
	[0-, 1-, ] SELECT id,user_id,main_page,extra FROM user_detail WHERE user_id IN (?,?)  args:[2,1]
	preload Blog
	[0-0, 0-1, 1-0, 1-1, ] SELECT id,created_at,updated_at,deleted_at,user_id,title,content FROM blog WHERE deleted_at IS NULL AND user_id IN (?,?)  args:[1,2]
	preload Friends
	[0-0, ] SELECT id,created_at,updated_at,deleted_at,name,age,sex FROM user WHERE deleted_at IS NULL AND id IN (?)  args:[2]
		preload Detail
		[0-0-, ] SELECT id,user_id,main_page,extra FROM user_detail WHERE user_id IN (?)  args:[2]
		preload Blog
		[0-0-0, 0-0-1, ] SELECT id,created_at,updated_at,deleted_at,user_id,title,content FROM blog WHERE deleted_at IS NULL AND user_id IN (?)  args:[2]
*/

use Err to view sql action error

var users []struct {
    ID     uint32
    Age    bool
    Detail *UserDetail
    Blog   []Blog
}
result, err = brick.Find(&users)
if err != nil {
    panic(err)
}
if err := result.Err(); err != nil {
    fmt.Printf("error:\n%s\n", err)
}

/*
error:
SELECT id,age FROM user WHERE deleted_at IS NULL  args:null errors(
	[0]sql: Scan error on column index 1: sql/driver: couldn't convert "18" into type bool
	[1]sql: Scan error on column index 1: sql/driver: couldn't convert "18" into type bool
)
*/
Selector

toyorm support following selector

operation \ selector OffsetOf Name string map[OffsetOf]interface{} map[string]interface{} struct
Update no no yes yes yes
Insert no no yes yes yes
Save no no yes yes yes
Where & Conditions yes yes yes yes yes
BindFields yes yes no no no
Preload & Custom Preload yes yes no no no
OrderBy yes yes no no no
Find no no no no yes

Collection

collection provide multiple database operation

ToyCollection

ToyCollection is basic of the collection , it like Toy

toyCollection, err = toyorm.OpenCollection("sqlite3", []string{"", ""}...)
CollectionBrick

CollectionBrick use to build grammar and operate the database, like ToyBrick

brick := toyCollection.Model(&User{})
Selector

Selector use to select database when Insert/Save

CollectionBrick has default selector dbPrimaryKeySelector

you can custom db selector

func idSelector(n int, keys ...interface{}) int {
	sum := 0
	for _, k := range keys {
		switch val := k.(type) {
		case int:
			sum += val
		case int32:
			sum += int(val)
		case uint:
			sum += int(val)
		case uint32:
			sum += int(val)
		default:
			panic("primary key type not match")
		}
	}
	return sum % n
}

brick = brick.Selector(idSelector)
id generator

in this mode,Field tag auto_increment was invalid

you need create id generator

// a context id generator
type IDGenerator map[*toyorm.Model]chan int

func (g IDGenerator) CollectionIDGenerate(ctx *toyorm.CollectionContext) error {
	if g[ctx.Brick.Model] == nil {
		idGenerate := make(chan int)
		go func() {
			current := 1
			for {
				// if have redis, use redis-cli
				idGenerate <- current
				current++
			}

		}()
		g[ctx.Brick.Model] = idGenerate
	}
	primaryKey := ctx.Brick.Model.GetOnePrimary()
	for _, record := range ctx.Result.Records.GetRecords() {
		if field := record.Field(primaryKey.Name()); field.IsValid() == false || toyorm.IsZero(field) {
			v := <-g[ctx.Brick.Model]
			record.SetField(primaryKey.Name(), reflect.ValueOf(v))
		}
	}
	return nil

}

// set id genetor to model context
toy.SetModelHandlers("Save", brick.Model, toyorm.CollectionHandlersChain{idGenerate.CollectionIDGenerate})
// set id genetor to all preload models context
for _, pBrick := range brick.MapPreloadBrick {
		toy.SetModelHandlers("Save", pBrick.Model, toyorm.CollectionHandlersChain{idGenerate.CollectionIDGenerate})
}
sql action

toy collection sql action is same as Toy

insert

users := []User{
    {Name: "Turing"},
    {Name: "Shannon"},
    {Name: "Ritchie"},
    {Name: "Jobs"},
}
result, err = userBrick.Insert(&users)
// error process

// view report log
fmt.Printf("report:\n%s", result.Report())

find

var jobs User
result, err = userBrick.Where(toyorm.ExprEqual, Offsetof(User{}.Name), "Jobs").Find(&jobs)
// error process

// view report log
fmt.Printf("report:\n%s", result.Report())

delete

result, err = userBrick.Delete(&jobs)
// error process

// view report log
fmt.Printf("delete report:\n%s\n", result.Report())
collection example

here

Documentation

Index

Constants

View Source
const (
	IgnoreNo    = IgnoreMode(0)
	IgnoreFalse = IgnoreMode(1 << iota)
	IgnoreZeroInt
	IgnoreZeroFloat
	IgnoreZeroComplex
	IgnoreNilString
	IgnoreNilPoint
	IgnoreZeroLen
	IgnoreNullStruct
	IgnoreNil  = IgnoreNilPoint | IgnoreZeroLen
	IgnoreZero = IgnoreFalse | IgnoreZeroInt | IgnoreZeroFloat | IgnoreZeroComplex | IgnoreNilString | IgnoreNilPoint | IgnoreZeroLen | IgnoreNullStruct
)
View Source
const (
	ResultActionExec = SqlActionType(iota)
	ResultActionQuery
)
View Source
const (
	ExprIgnore       = ""
	ExprAnd          = "AND"
	ExprOr           = "OR"
	ExprNot          = "NOT"
	ExprEqual        = "="
	ExprNotEqual     = "<>"
	ExprGreater      = ">"
	ExprGreaterEqual = ">="
	ExprLess         = "<"
	ExprLessEqual    = "<="
	ExprBetween      = "BETWEEN"
	ExprNotBetween   = "NOT BETWEEN"
	ExprIn           = "IN"
	ExprNotIn        = "NOT IN"
	ExprLike         = "LIKE"
	ExprNotLike      = "NOT LIKE"
	ExprNull         = "NULL"
	ExprNotNull      = "NOT NULL"
)

Variables

View Source
var (
	ErrInvalidTag        = errors.New("invalid tag")
	ErrInvalidSearchTree = errors.New("invalid search tree")
	ErrNotMatchDialect   = errors.New("not match dialect")
)

Functions

func CollectionHandlerAssignToAllDb

func CollectionHandlerAssignToAllDb(ctx *CollectionContext) error

assign after handlers to all db

func CollectionHandlerCreateTable

func CollectionHandlerCreateTable(ctx *CollectionContext) error

func CollectionHandlerDropTable

func CollectionHandlerDropTable(ctx *CollectionContext) (err error)

func CollectionHandlerDropTablePreload

func CollectionHandlerDropTablePreload(option string) func(ctx *CollectionContext) error

preload schedule oneToOne -> oneToMany -> current model -> manyToMany(sub -> middle) -> Next() -> belongTo

func CollectionHandlerExistTableAbort

func CollectionHandlerExistTableAbort(ctx *CollectionContext) error

func CollectionHandlerFind

func CollectionHandlerFind(ctx *CollectionContext) error

func CollectionHandlerFindOne

func CollectionHandlerFindOne(ctx *CollectionContext) error

func CollectionHandlerFindOneAssignDbIndex

func CollectionHandlerFindOneAssignDbIndex(ctx *CollectionContext) error

func CollectionHandlerInsert

func CollectionHandlerInsert(ctx *CollectionContext) error

func CollectionHandlerInsertAssignDbIndex

func CollectionHandlerInsertAssignDbIndex(ctx *CollectionContext) error

func CollectionHandlerInsertTimeGenerate

func CollectionHandlerInsertTimeGenerate(ctx *CollectionContext) error

func CollectionHandlerNotExistTableAbort

func CollectionHandlerNotExistTableAbort(ctx *CollectionContext) error

func CollectionHandlerPreloadContainerCheck

func CollectionHandlerPreloadContainerCheck(ctx *CollectionContext) error

func CollectionHandlerPreloadFind

func CollectionHandlerPreloadFind(ctx *CollectionContext) error

func CollectionHandlerPreloadInsertOrSave

func CollectionHandlerPreloadInsertOrSave(option string) func(*CollectionContext) error

func CollectionHandlerSave

func CollectionHandlerSave(ctx *CollectionContext) error

func CollectionHandlerSaveTimeGenerate

func CollectionHandlerSaveTimeGenerate(ctx *CollectionContext) error

func CollectionHandlerSimplePreload

func CollectionHandlerSimplePreload(option string) func(ctx *CollectionContext) error

preload schedule belongTo -> Next() -> oneToOne -> oneToMany -> manyToMany(sub -> middle)

func CollectionHandlerSoftDeleteCheck

func CollectionHandlerSoftDeleteCheck(ctx *CollectionContext) error

func CollectionHandlerUpdate

func CollectionHandlerUpdate(ctx *CollectionContext) error

func CollectionHandlerUpdateTimeGenerate

func CollectionHandlerUpdateTimeGenerate(ctx *CollectionContext) error

func DefaultCollectionTemplateExec

func DefaultCollectionTemplateExec(ctx *CollectionContext) map[string]BasicExec

func DefaultTemplateExec

func DefaultTemplateExec(ctx *Context) map[string]BasicExec

func GetBelongsIDFieldName

func GetBelongsIDFieldName(subModel *Model, containerField Field) string

func GetRelationFieldName

func GetRelationFieldName(subModel *Model) string

generate a default field name with relation model

func GetStructFields

func GetStructFields(_type reflect.Type) []reflect.StructField

get all StructField with struct field and its embed field

func GetStructValueFields

func GetStructValueFields(value reflect.Value) []reflect.Value

get all Value with struct field and its embed struct field

func HandlerCollectionHardDelete

func HandlerCollectionHardDelete(ctx *CollectionContext) error

func HandlerCollectionPreloadDelete

func HandlerCollectionPreloadDelete(ctx *CollectionContext) error

func HandlerCollectionSearchWithPrimaryKey

func HandlerCollectionSearchWithPrimaryKey(ctx *CollectionContext) error

func HandlerCollectionSoftDelete

func HandlerCollectionSoftDelete(ctx *CollectionContext) error

func HandlerCollectionSoftDeleteCheck

func HandlerCollectionSoftDeleteCheck(ctx *CollectionContext) error

func HandlerCreateTable

func HandlerCreateTable(ctx *Context) error

func HandlerCreateTablePreload

func HandlerCreateTablePreload(option string) func(ctx *Context) error

preload schedule belongTo -> Next() -> oneToOne -> oneToMany -> manyToMany(sub -> middle)

func HandlerDropTable

func HandlerDropTable(ctx *Context) (err error)

func HandlerDropTablePreload

func HandlerDropTablePreload(option string) func(ctx *Context) error

preload schedule oneToOne -> oneToMany -> current model -> manyToMany(sub -> middle) -> Next() -> belongTo

func HandlerExistTableAbort

func HandlerExistTableAbort(ctx *Context) error

func HandlerFind

func HandlerFind(ctx *Context) error

func HandlerHardDelete

func HandlerHardDelete(ctx *Context) error

func HandlerInsert

func HandlerInsert(ctx *Context) error

func HandlerInsertTimeGenerate

func HandlerInsertTimeGenerate(ctx *Context) error

func HandlerNotExistTableAbort

func HandlerNotExistTableAbort(ctx *Context) error

func HandlerPreloadContainerCheck

func HandlerPreloadContainerCheck(ctx *Context) error

func HandlerPreloadDelete

func HandlerPreloadDelete(ctx *Context) error

func HandlerPreloadFind

func HandlerPreloadFind(ctx *Context) error

func HandlerPreloadInsertOrSave

func HandlerPreloadInsertOrSave(option string) func(*Context) error

func HandlerPreloadOnJoinFind

func HandlerPreloadOnJoinFind(ctx *Context) error

func HandlerSave

func HandlerSave(ctx *Context) error

if have not primary ,try to insert else try to replace

func HandlerSaveTimeGenerate

func HandlerSaveTimeGenerate(ctx *Context) error

func HandlerSearchWithPrimaryKey

func HandlerSearchWithPrimaryKey(ctx *Context) error

func HandlerSoftDelete

func HandlerSoftDelete(ctx *Context) error

func HandlerSoftDeleteCheck

func HandlerSoftDeleteCheck(ctx *Context) error

func HandlerUpdate

func HandlerUpdate(ctx *Context) error

func HandlerUpdateTimeGenerate

func HandlerUpdateTimeGenerate(ctx *Context) error

func IsZero

func IsZero(v reflect.Value) bool

to check value is zero

func LoopIndirect

func LoopIndirect(vValue reflect.Value) reflect.Value

loop to get ptr value elem when its type is not ptr

func LoopIndirectAndNew

func LoopIndirectAndNew(vValue reflect.Value) reflect.Value

loop to get ptr value elem when its type is not ptr and if value is zero, set a new one

func LoopTypeIndirect

func LoopTypeIndirect(_type reflect.Type) reflect.Type

loop to get ptr type elem when its type is not ptr/slice

func LoopTypeIndirectSliceAndPtr

func LoopTypeIndirectSliceAndPtr(_type reflect.Type) reflect.Type

loop to get ptr/slice type elem when its type is not ptr/slice

func ModelName

func ModelName(_type reflect.Type) string

get model name with type

func NewField

func NewField(f *reflect.StructField, table_name string) *modelField

func SafeAppend

func SafeAppend(l reflect.Value, x ...reflect.Value) reflect.Value

if value type is ptr to l elem type , try to get its elem and append to l if l elem type is ptr to x type , try to make x ptr and append to l

func SqlNameConvert

func SqlNameConvert(name string) string

column convert rule: User => user UserName => user_name UserID => user_id OneToOne => one_to_one

func ToSqlType

func ToSqlType(_type reflect.Type) (sqlType string)

Types

type AffectNode

type AffectNode struct {
	Val    int
	Ignore bool
	Next   *AffectNode
}

func IgnoreAffectNode

func IgnoreAffectNode(next *AffectNode) *AffectNode

func NewAffectNode

func NewAffectNode(val int, next *AffectNode) *AffectNode

type BasicExec

type BasicExec struct {
	// contains filtered or unexported fields
}

type BelongToPreload

type BelongToPreload struct {
	Model         *Model
	SubModel      *Model
	RelationField Field
	// used to save other table value
	ContainerField Field
}

this is describe one to one relationship with table and its sub table e.g select * from sub_table where id = (table.RelationField).value

type BrickColumn

type BrickColumn struct {
	// contains filtered or unexported fields
}

func (BrickColumn) Column

func (c BrickColumn) Column() string

type BrickColumnList

type BrickColumnList []*BrickColumn

func (BrickColumnList) ToColumnList

func (l BrickColumnList) ToColumnList() []Column

type BrickColumnValue

type BrickColumnValue struct {
	BrickColumn
	// contains filtered or unexported fields
}

func (BrickColumnValue) Value

func (v BrickColumnValue) Value() reflect.Value

type BrickColumnValueList

type BrickColumnValueList []*BrickColumnValue

func (BrickColumnValueList) ToValueList

func (l BrickColumnValueList) ToValueList() []ColumnValue

type BrickCommon

type BrickCommon struct {
	Model             *Model
	BelongToPreload   map[string]*BelongToPreload
	OneToOnePreload   map[string]*OneToOnePreload
	OneToManyPreload  map[string]*OneToManyPreload
	ManyToManyPreload map[string]*ManyToManyPreload

	// use by find/scan/insert/update/replace/where ,if FieldsSelector[Mode] is set,then ignoreModeSelector will failure
	// FieldsSelector[ModeDefault] can work on all Mode when they specified Mode not set
	FieldsSelector [ModeEnd][]Field
	// contains filtered or unexported fields
}

func (*BrickCommon) CopyBelongToPreload

func (t *BrickCommon) CopyBelongToPreload() map[string]*BelongToPreload

func (*BrickCommon) CopyManyToManyPreload

func (t *BrickCommon) CopyManyToManyPreload() map[string]*ManyToManyPreload

func (*BrickCommon) CopyOneToManyPreload

func (t *BrickCommon) CopyOneToManyPreload() map[string]*OneToManyPreload

func (*BrickCommon) CopyOneToOnePreload

func (t *BrickCommon) CopyOneToOnePreload() map[string]*OneToOnePreload

func (*BrickCommon) ToDesc

func (t *BrickCommon) ToDesc(v interface{}) *BrickColumn

use for order by

type CollectionBrick

type CollectionBrick struct {
	Toy *ToyCollection

	MapPreloadBrick map[string]*CollectionBrick

	//orderBy []Column
	Search SearchList

	BrickCommon
	// contains filtered or unexported fields
}

func NewCollectionBrick

func NewCollectionBrick(toy *ToyCollection, model *Model) *CollectionBrick

func (*CollectionBrick) And

func (*CollectionBrick) BindDefaultFields

func (t *CollectionBrick) BindDefaultFields(args ...interface{}) *CollectionBrick

func (*CollectionBrick) BindFields

func (t *CollectionBrick) BindFields(mode Mode, args ...interface{}) *CollectionBrick

func (*CollectionBrick) Clone

func (t *CollectionBrick) Clone() *CollectionBrick

func (*CollectionBrick) ConditionExec

func (t *CollectionBrick) ConditionExec() ExecValue

func (*CollectionBrick) Conditions

func (t *CollectionBrick) Conditions(search SearchList) *CollectionBrick

func (*CollectionBrick) CopyMapPreloadBrick

func (t *CollectionBrick) CopyMapPreloadBrick() map[string]*CollectionBrick

func (*CollectionBrick) CopyStatus

func (t *CollectionBrick) CopyStatus(statusBrick *CollectionBrick) *CollectionBrick

func (*CollectionBrick) Count

func (t *CollectionBrick) Count() (count int, err error)

func (*CollectionBrick) CountExec

func (t *CollectionBrick) CountExec() (exec ExecValue)

func (*CollectionBrick) CreateTable

func (t *CollectionBrick) CreateTable() (*Result, error)

func (*CollectionBrick) CreateTableIfNotExist

func (t *CollectionBrick) CreateTableIfNotExist() (*Result, error)

func (*CollectionBrick) CustomBelongToPreload

func (t *CollectionBrick) CustomBelongToPreload(container, relationship interface{}, args ...interface{}) *CollectionBrick

func (*CollectionBrick) CustomManyToManyPreload

func (t *CollectionBrick) CustomManyToManyPreload(middleStruct, container, relation, subRelation interface{}, args ...interface{}) *CollectionBrick

func (*CollectionBrick) CustomOneToManyPreload

func (t *CollectionBrick) CustomOneToManyPreload(container, relationship interface{}, args ...interface{}) *CollectionBrick

func (*CollectionBrick) CustomOneToOnePreload

func (t *CollectionBrick) CustomOneToOnePreload(container, relationship interface{}, args ...interface{}) *CollectionBrick

func (*CollectionBrick) DBIndex

func (t *CollectionBrick) DBIndex(i int) *CollectionBrick

func (*CollectionBrick) Debug

func (t *CollectionBrick) Debug() *CollectionBrick

func (*CollectionBrick) Delete

func (t *CollectionBrick) Delete(v interface{}) (*Result, error)

func (*CollectionBrick) DeleteExec

func (t *CollectionBrick) DeleteExec() ExecValue

func (*CollectionBrick) DeleteWithConditions

func (t *CollectionBrick) DeleteWithConditions() (*Result, error)

func (*CollectionBrick) DropTable

func (t *CollectionBrick) DropTable() (*Result, error)

func (*CollectionBrick) DropTableIfExist

func (t *CollectionBrick) DropTableIfExist() (*Result, error)

func (*CollectionBrick) Enter

func (t *CollectionBrick) Enter() *CollectionBrick

return it parent CollectionBrick it will panic when the parent CollectionBrick is nil

func (*CollectionBrick) Exec

func (t *CollectionBrick) Exec(exec ExecValue, i int) (sql.Result, error)

func (*CollectionBrick) Find

func (t *CollectionBrick) Find(v interface{}) (*Result, error)

func (*CollectionBrick) FindExec

func (t *CollectionBrick) FindExec(records ModelRecordFieldTypes) ExecValue

func (*CollectionBrick) GetContext

func (t *CollectionBrick) GetContext(option string, records ModelRecords) *CollectionContext

func (*CollectionBrick) HasTable

func (t *CollectionBrick) HasTable() ([]bool, error)

func (*CollectionBrick) IgnoreMode

func (t *CollectionBrick) IgnoreMode(s Mode, ignore IgnoreMode) *CollectionBrick

func (*CollectionBrick) Insert

func (t *CollectionBrick) Insert(v interface{}) (*Result, error)

insert can receive three type data struct map[offset]interface{} map[int]interface{} insert is difficult that have preload data

func (*CollectionBrick) InsertExec

func (t *CollectionBrick) InsertExec(record ModelRecord) ExecValue

func (*CollectionBrick) Or

func (*CollectionBrick) Preload

func (t *CollectionBrick) Preload(fv interface{}) *CollectionBrick

return

func (*CollectionBrick) Query

func (t *CollectionBrick) Query(exec ExecValue, i int) (*sql.Rows, error)

func (*CollectionBrick) QueryRow

func (t *CollectionBrick) QueryRow(exec ExecValue, i int) *sql.Row

func (*CollectionBrick) ReplaceExec

func (t *CollectionBrick) ReplaceExec(record ModelRecord) ExecValue

func (*CollectionBrick) RightValuePreload

func (t *CollectionBrick) RightValuePreload(fv interface{}) *CollectionBrick

this module is get preload which is right middle field name in many-to-many mode it only use for sub model type is same with main model type e.g

User{
    ID int `toyorm:"primary key"`
    Friend []User
}

now the main model middle field name is L_UserID, sub model middle field name is R_UserID if you want to get preload with main model middle field name == R_UserID use RightValuePreload

func (*CollectionBrick) Save

func (t *CollectionBrick) Save(v interface{}) (*Result, error)

func (*CollectionBrick) Scope

func (*CollectionBrick) Selector

func (t *CollectionBrick) Selector(selector DBPrimarySelector) *CollectionBrick

func (*CollectionBrick) Template

func (t *CollectionBrick) Template(temp string, args ...interface{}) *CollectionBrick

func (*CollectionBrick) Update

func (t *CollectionBrick) Update(v interface{}) (*Result, error)

func (*CollectionBrick) UpdateExec

func (t *CollectionBrick) UpdateExec(record ModelRecord) ExecValue

func (*CollectionBrick) Where

func (t *CollectionBrick) Where(expr SearchExpr, key interface{}, v ...interface{}) *CollectionBrick

where will clean old condition

type CollectionBrickAnd

type CollectionBrickAnd struct {
	Brick *CollectionBrick
}

func (CollectionBrickAnd) Condition

func (t CollectionBrickAnd) Condition(expr SearchExpr, key interface{}, v ...interface{}) *CollectionBrick

func (CollectionBrickAnd) Conditions

func (t CollectionBrickAnd) Conditions(search SearchList) *CollectionBrick

type CollectionBrickOr

type CollectionBrickOr struct {
	Brick *CollectionBrick
}

func (CollectionBrickOr) Condition

func (t CollectionBrickOr) Condition(expr SearchExpr, key interface{}, v ...interface{}) *CollectionBrick

func (CollectionBrickOr) Conditions

func (t CollectionBrickOr) Conditions(search SearchList) *CollectionBrick

type CollectionContext

type CollectionContext struct {
	Brick  *CollectionBrick
	Result *Result
	// contains filtered or unexported fields
}

func NewCollectionContext

func NewCollectionContext(handlers CollectionHandlersChain, brick *CollectionBrick, columns ModelRecords) *CollectionContext

func (*CollectionContext) Abort

func (c *CollectionContext) Abort()

func (*CollectionContext) IsAborted

func (c *CollectionContext) IsAborted() bool

func (*CollectionContext) Next

func (c *CollectionContext) Next() error

func (*CollectionContext) Value

func (c *CollectionContext) Value(v interface{}) interface{}

type CollectionExecAction

type CollectionExecAction struct {
	//Type   ResultType
	Exec   ExecValue
	Result sql.Result

	Error error
	// contains filtered or unexported fields
}

func (CollectionExecAction) AffectData

func (r CollectionExecAction) AffectData() []int

func (CollectionExecAction) Err

func (r CollectionExecAction) Err() error

func (CollectionExecAction) SetAffectData

func (r CollectionExecAction) SetAffectData(d []int)

func (CollectionExecAction) String

func (r CollectionExecAction) String() string

func (CollectionExecAction) Type

type CollectionHandlerFunc

type CollectionHandlerFunc func(c *CollectionContext) error

type CollectionHandlersChain

type CollectionHandlersChain []CollectionHandlerFunc

type CollectionQueryAction

type CollectionQueryAction struct {
	Exec ExecValue

	Error []error
	// contains filtered or unexported fields
}

func (CollectionQueryAction) AffectData

func (r CollectionQueryAction) AffectData() []int

func (CollectionQueryAction) Err

func (r CollectionQueryAction) Err() error

func (CollectionQueryAction) SetAffectData

func (r CollectionQueryAction) SetAffectData(d []int)

func (CollectionQueryAction) String

func (r CollectionQueryAction) String() string

func (CollectionQueryAction) Type

type Column

type Column interface {
	Column() string
}

func FindColumnFactory

func FindColumnFactory(fieldTypes ModelRecordFieldTypes, brick *ToyBrick) ([]Column, func(ModelRecord) []interface{})

get columns and scanner generator

type ColumnName

type ColumnName interface {
	Column
	Name() string
}

type ColumnValue

type ColumnValue interface {
	Column
	Value() reflect.Value
}

type Context

type Context struct {
	Brick  *ToyBrick
	Result *Result
	// contains filtered or unexported fields
}

func NewContext

func NewContext(handlers HandlersChain, brick *ToyBrick, columns ModelRecords) *Context

func (*Context) Abort

func (c *Context) Abort()

func (*Context) IsAborted

func (c *Context) IsAborted() bool

func (*Context) Next

func (c *Context) Next() error

func (*Context) Value

func (c *Context) Value(v interface{}) interface{}

type DBPrimarySelector

type DBPrimarySelector func(n int, key ...interface{}) int

type DBValSelector

type DBValSelector interface {
	Select(int) int
}

type DefaultDialect

type DefaultDialect struct{}

func (DefaultDialect) AddForeignKey

func (dia DefaultDialect) AddForeignKey(model, relationModel *Model, ForeignKeyField Field) ExecValue

func (DefaultDialect) ConditionExec

func (dia DefaultDialect) ConditionExec(search SearchList, limit, offset int, orderBy []Column, groupBy []Column) ExecValue

func (DefaultDialect) CountExec

func (dia DefaultDialect) CountExec(model *Model) ExecValue

func (DefaultDialect) DeleteExec

func (dia DefaultDialect) DeleteExec(model *Model) (exec ExecValue)

func (DefaultDialect) DropForeignKey

func (dia DefaultDialect) DropForeignKey(model *Model, ForeignKeyField Field) ExecValue

func (DefaultDialect) DropTable

func (dia DefaultDialect) DropTable(m *Model) ExecValue

func (DefaultDialect) FindExec

func (dia DefaultDialect) FindExec(model *Model, columns []Column, alias string) ExecValue

func (DefaultDialect) InsertExec

func (dia DefaultDialect) InsertExec(model *Model, columnValues []ColumnValue) ExecValue

func (DefaultDialect) InsertExecutor

func (dia DefaultDialect) InsertExecutor(db Executor, exec ExecValue, debugPrinter func(string, string, error)) (sql.Result, error)

func (DefaultDialect) JoinExec

func (dia DefaultDialect) JoinExec(mainSwap *JoinSwap) ExecValue

func (DefaultDialect) ReplaceExec

func (dia DefaultDialect) ReplaceExec(model *Model, columnValues []ColumnValue) ExecValue

func (DefaultDialect) SearchExec

func (dia DefaultDialect) SearchExec(s SearchList) ExecValue

func (DefaultDialect) TemplateExec

func (dia DefaultDialect) TemplateExec(tExec BasicExec, execs map[string]BasicExec) (ExecValue, error)

func (DefaultDialect) UpdateExec

func (dia DefaultDialect) UpdateExec(model *Model, columnValues []ColumnValue) ExecValue

type DefaultExec

type DefaultExec struct {
	// contains filtered or unexported fields
}

not process source str, Source() == Query()

func (DefaultExec) Append

func (e DefaultExec) Append(query string, args ...interface{}) ExecValue

func (DefaultExec) Args

func (e DefaultExec) Args() []interface{}

func (DefaultExec) JsonArgs

func (e DefaultExec) JsonArgs() string

func (DefaultExec) Query

func (e DefaultExec) Query() string

func (DefaultExec) Source

func (e DefaultExec) Source() string

type Dialect

type Dialect interface {
	// some database like postgres not support LastInsertId, need QueryRow to get the return id
	InsertExecutor(Executor, ExecValue, func(string, string, error)) (sql.Result, error)
	HasTable(*Model) ExecValue
	CreateTable(*Model, map[string]ForeignKey) []ExecValue
	DropTable(*Model) ExecValue
	ConditionExec(search SearchList, limit, offset int, orderBy []Column, groupBy []Column) ExecValue
	FindExec(model *Model, columns []Column, alias string) ExecValue
	UpdateExec(*Model, []ColumnValue) ExecValue
	DeleteExec(*Model) ExecValue
	InsertExec(*Model, []ColumnValue) ExecValue
	ReplaceExec(*Model, []ColumnValue) ExecValue
	AddForeignKey(model, relationModel *Model, ForeignKeyField Field) ExecValue
	DropForeignKey(model *Model, ForeignKeyField Field) ExecValue
	CountExec(*Model) ExecValue
	SearchExec(search SearchList) ExecValue
	TemplateExec(BasicExec, map[string]BasicExec) (ExecValue, error)
	JoinExec(*JoinSwap) ExecValue
}

type ErrCollectionClose

type ErrCollectionClose map[int]error

func (ErrCollectionClose) Error

func (e ErrCollectionClose) Error() string

type ErrCollectionDBSelectorNotFound

type ErrCollectionDBSelectorNotFound struct {
}

func (ErrCollectionDBSelectorNotFound) Error

type ErrCollectionExec

type ErrCollectionExec map[int]error

func (ErrCollectionExec) Error

func (e ErrCollectionExec) Error() string

type ErrCollectionQuery

type ErrCollectionQuery map[int]error

func (ErrCollectionQuery) Error

func (e ErrCollectionQuery) Error() string

type ErrCollectionQueryRow

type ErrCollectionQueryRow map[int]error

func (ErrCollectionQueryRow) Error

func (e ErrCollectionQueryRow) Error() string

type ErrDbIndexNotSet

type ErrDbIndexNotSet struct{}

func (ErrDbIndexNotSet) Error

func (e ErrDbIndexNotSet) Error() string

type ErrInvalidModelName

type ErrInvalidModelName struct{}

func (ErrInvalidModelName) Error

func (e ErrInvalidModelName) Error() string

type ErrInvalidModelType

type ErrInvalidModelType string

func (ErrInvalidModelType) Error

func (e ErrInvalidModelType) Error() string

type ErrInvalidPreloadField

type ErrInvalidPreloadField struct {
	ModelName string
	FieldName string
}

func (ErrInvalidPreloadField) Error

func (e ErrInvalidPreloadField) Error() string

type ErrInvalidRecordType

type ErrInvalidRecordType struct {
}

func (ErrInvalidRecordType) Error

func (e ErrInvalidRecordType) Error() string

type ErrLastInsertId

type ErrLastInsertId struct{}

func (ErrLastInsertId) Error

func (e ErrLastInsertId) Error() string

type ErrNotSupportRowsAffected

type ErrNotSupportRowsAffected struct{}

func (ErrNotSupportRowsAffected) Error

type ErrRepeatField

type ErrRepeatField struct {
	ModelName string
	FieldName string
}

func (ErrRepeatField) Error

func (e ErrRepeatField) Error() string

type ErrSameColumnName

type ErrSameColumnName struct {
	ModelName    string
	Same         string
	OldFieldName string
	NewFieldName string
}

func (ErrSameColumnName) Error

func (e ErrSameColumnName) Error() string

type ErrTemplateExecInvalidWord

type ErrTemplateExecInvalidWord struct {
	Word string
}

func (ErrTemplateExecInvalidWord) Error

type ErrZeroPrimaryKey

type ErrZeroPrimaryKey struct{ Model *Model }

func (ErrZeroPrimaryKey) Error

func (e ErrZeroPrimaryKey) Error() string

type ExecAction

type ExecAction struct {
	//Type   ResultType
	Exec   ExecValue
	Result sql.Result

	Error error
	// contains filtered or unexported fields
}

func (ExecAction) AffectData

func (r ExecAction) AffectData() []int

func (ExecAction) Err

func (r ExecAction) Err() error

func (ExecAction) SetAffectData

func (r ExecAction) SetAffectData(d []int)

func (ExecAction) String

func (r ExecAction) String() string

func (ExecAction) Type

func (r ExecAction) Type() SqlActionType

type ExecValue

type ExecValue interface {
	Source() string
	Query() string
	Args() []interface{}
	Append(query string, args ...interface{}) ExecValue
	JsonArgs() string
}

type Executor

type Executor interface {
	Exec(query string, args ...interface{}) (sql.Result, error)
	QueryRow(query string, args ...interface{}) *sql.Row
	Query(query string, args ...interface{}) (*sql.Rows, error)
}

type Field

type Field interface {
	Column
	Name() string
	Offset() uintptr
	IsPrimary() bool
	AutoIncrement() bool
	Index() string
	UniqueIndex() string
	IsForeign() bool
	Attr(string) string
	Attrs() map[string]string
	SqlType() string
	StructField() reflect.StructField
	JoinWith() string
}

func GetMiddleField

func GetMiddleField(model, middleModel *Model, leftOrRight bool) Field

type ForeignKey

type ForeignKey struct {
	Model *Model
	Field Field
}

type HandlerFunc

type HandlerFunc func(c *Context) error

type HandlersChain

type HandlersChain []HandlerFunc

type IgnoreMode

type IgnoreMode int

func (IgnoreMode) Ignore

func (ignoreMode IgnoreMode) Ignore(v reflect.Value) (ignore bool)

type Join

type Join struct {
	Model     *Model
	SubModel  *Model
	Container Field
	OnMain    Field
	OnSub     Field
}

type JoinSwap

type JoinSwap struct {
	OwnOrderBy        []int
	OwnGroupBy        []int
	OwnSearch         []int
	Alias             string
	FieldsSelector    [ModeEnd][]Field
	SwapMap           map[string]*JoinSwap
	JoinMap           map[string]*Join
	MapPreloadBrick   map[string]*ToyBrick
	BelongToPreload   map[string]*BelongToPreload
	OneToOnePreload   map[string]*OneToOnePreload
	OneToManyPreload  map[string]*OneToManyPreload
	ManyToManyPreload map[string]*ManyToManyPreload
}

join will replace attribute

func NewJoinSwap

func NewJoinSwap(alias string) *JoinSwap

func (*JoinSwap) Copy

func (m *JoinSwap) Copy() *JoinSwap

type ManyToManyPreload

type ManyToManyPreload struct {
	MiddleModel      *Model
	Model            *Model
	SubModel         *Model
	ContainerField   Field
	RelationField    Field
	SubRelationField Field
}

this is describe many to many relationship with table and its sub table e.g select * from middle_table where table.id = table.id and sub_table.id = (table.RelationField).value

type Mode

type Mode int8
const (
	ModeDefault Mode = iota
	ModeInsert
	ModeReplace
	ModeUpdate
	ModeScan
	ModeSelect
	ModeCondition
	ModePreload
	ModeEnd
)

type Model

type Model struct {
	Name              string
	ReflectType       reflect.Type
	AllFields         []*modelField
	SqlFields         []*modelField
	OffsetFields      map[uintptr]*modelField
	NameFields        map[string]*modelField
	SqlFieldMap       map[string]*modelField
	PrimaryFields     []*modelField
	IndexFields       map[string][]*modelField
	UniqueIndexFields map[string][]*modelField
	StructFieldFields map[reflect.Type][]*modelField
	JoinWithMap       map[string]*modelField
}

table struct used to save all sql attribute with struct column is table name attribute AllFields is all struct field and it's Anonymous struct SqlFields is all about sql field OffsetFields is map field offset NameFields is map field name PrimaryFields is all about primary key field IndexFields is all about index fields UniqueIndexFields is all about unique index fields StructFieldFields is map unknown struct type or slice struct type

func NewMiddleModel

func NewMiddleModel(model, subModel *Model) *Model

func NewModel

func NewModel(_type reflect.Type) *Model

func (*Model) GetFieldWithName

func (m *Model) GetFieldWithName(name string) Field

func (*Model) GetIndexMap

func (m *Model) GetIndexMap() map[string][]Field

func (*Model) GetNameFieldMap

func (m *Model) GetNameFieldMap() map[string]Field

func (*Model) GetOffsetField

func (m *Model) GetOffsetField(offset uintptr) Field

func (*Model) GetOffsetFieldMap

func (m *Model) GetOffsetFieldMap() map[uintptr]Field

func (*Model) GetOnePrimary

func (m *Model) GetOnePrimary() Field

func (*Model) GetPosField

func (m *Model) GetPosField(pos int) Field

func (*Model) GetPosFields

func (m *Model) GetPosFields(pos []int) []Field

func (*Model) GetPrimary

func (m *Model) GetPrimary() []Field

func (*Model) GetSqlFields

func (m *Model) GetSqlFields() []Field

func (*Model) GetUniqueIndexMap

func (m *Model) GetUniqueIndexMap() map[string][]Field

type ModelDefault

type ModelDefault struct {
	ID        uint32     `toyorm:"primary key;auto_increment"`
	CreatedAt time.Time  `toyorm:"NULL"`
	UpdatedAt time.Time  `toyorm:"NULL"`
	DeletedAt *time.Time `toyorm:"index;NULL"`
}

type ModelGroupBy

type ModelGroupBy map[interface{}][]ModelIndexRecord

func (ModelGroupBy) Keys

func (m ModelGroupBy) Keys() []interface{}

type ModelIndexRecord

type ModelIndexRecord struct {
	ModelRecord
	Index int
}

type ModelNameMapRecord

type ModelNameMapRecord struct {
	FieldValues map[string]reflect.Value
	// contains filtered or unexported fields
}

func NewNameMapRecord

func NewNameMapRecord(model *Model, v reflect.Value) *ModelNameMapRecord

func (*ModelNameMapRecord) AllField

func (m *ModelNameMapRecord) AllField() map[string]reflect.Value

func (*ModelNameMapRecord) Field

func (m *ModelNameMapRecord) Field(name string) reflect.Value

func (*ModelNameMapRecord) FieldAddress

func (m *ModelNameMapRecord) FieldAddress(name string) reflect.Value

func (*ModelNameMapRecord) GetFieldType

func (m *ModelNameMapRecord) GetFieldType(name string) reflect.Type

func (*ModelNameMapRecord) IsVariableContainer

func (m *ModelNameMapRecord) IsVariableContainer() bool

func (*ModelNameMapRecord) SetField

func (m *ModelNameMapRecord) SetField(name string, value reflect.Value)

func (*ModelNameMapRecord) Source

func (m *ModelNameMapRecord) Source() reflect.Value

type ModelNameMapRecords

type ModelNameMapRecords struct {
	FieldValuesList []map[string]reflect.Value
	// contains filtered or unexported fields
}

func NewNameMapRecords

func NewNameMapRecords(model *Model, v reflect.Value) *ModelNameMapRecords

func (*ModelNameMapRecords) Add

func (*ModelNameMapRecords) ElemType

func (m *ModelNameMapRecords) ElemType() reflect.Type

func (*ModelNameMapRecords) GetFieldAddressType

func (m *ModelNameMapRecords) GetFieldAddressType(name string) reflect.Type

func (*ModelNameMapRecords) GetFieldType

func (m *ModelNameMapRecords) GetFieldType(name string) reflect.Type

func (*ModelNameMapRecords) GetRecord

func (m *ModelNameMapRecords) GetRecord(i int) ModelRecord

func (*ModelNameMapRecords) GetRecords

func (m *ModelNameMapRecords) GetRecords() []ModelRecord

func (*ModelNameMapRecords) GroupBy

func (m *ModelNameMapRecords) GroupBy(key string) ModelGroupBy

func (*ModelNameMapRecords) GroupByFunc

func (m *ModelNameMapRecords) GroupByFunc(key string, fn func(int, ModelRecord))

func (*ModelNameMapRecords) IsVariableContainer

func (m *ModelNameMapRecords) IsVariableContainer() bool

func (*ModelNameMapRecords) Len

func (m *ModelNameMapRecords) Len() int

func (*ModelNameMapRecords) Source

func (m *ModelNameMapRecords) Source() reflect.Value

type ModelOffsetMapRecord

type ModelOffsetMapRecord struct {
	FieldValues map[string]reflect.Value
	// contains filtered or unexported fields
}

func NewOffsetMapRecord

func NewOffsetMapRecord(model *Model, v reflect.Value) *ModelOffsetMapRecord

func (*ModelOffsetMapRecord) AllField

func (m *ModelOffsetMapRecord) AllField() map[string]reflect.Value

func (*ModelOffsetMapRecord) Field

func (m *ModelOffsetMapRecord) Field(name string) reflect.Value

func (*ModelOffsetMapRecord) FieldAddress

func (m *ModelOffsetMapRecord) FieldAddress(name string) reflect.Value

func (*ModelOffsetMapRecord) GetFieldType

func (m *ModelOffsetMapRecord) GetFieldType(name string) reflect.Type

func (*ModelOffsetMapRecord) IsVariableContainer

func (m *ModelOffsetMapRecord) IsVariableContainer() bool

func (*ModelOffsetMapRecord) SetField

func (m *ModelOffsetMapRecord) SetField(name string, value reflect.Value)

func (*ModelOffsetMapRecord) Source

func (m *ModelOffsetMapRecord) Source() reflect.Value

type ModelOffsetMapRecords

type ModelOffsetMapRecords struct {
	FieldValuesList []map[string]reflect.Value
	// contains filtered or unexported fields
}

func NewOffsetMapRecords

func NewOffsetMapRecords(model *Model, m reflect.Value) *ModelOffsetMapRecords

func (*ModelOffsetMapRecords) Add

func (*ModelOffsetMapRecords) ElemType

func (m *ModelOffsetMapRecords) ElemType() reflect.Type

func (*ModelOffsetMapRecords) GetFieldAddressType

func (m *ModelOffsetMapRecords) GetFieldAddressType(name string) reflect.Type

func (*ModelOffsetMapRecords) GetFieldType

func (m *ModelOffsetMapRecords) GetFieldType(name string) reflect.Type

func (*ModelOffsetMapRecords) GetRecord

func (m *ModelOffsetMapRecords) GetRecord(i int) ModelRecord

func (*ModelOffsetMapRecords) GetRecords

func (m *ModelOffsetMapRecords) GetRecords() []ModelRecord

func (*ModelOffsetMapRecords) GroupBy

func (m *ModelOffsetMapRecords) GroupBy(key string) ModelGroupBy

func (*ModelOffsetMapRecords) IsVariableContainer

func (m *ModelOffsetMapRecords) IsVariableContainer() bool

func (*ModelOffsetMapRecords) Len

func (m *ModelOffsetMapRecords) Len() int

func (*ModelOffsetMapRecords) Source

func (m *ModelOffsetMapRecords) Source() reflect.Value

type ModelRecord

type ModelRecord interface {
	AllField() map[string]reflect.Value
	SetField(field string, v reflect.Value)
	Field(field string) reflect.Value
	FieldAddress(field string) reflect.Value
	IsVariableContainer() bool
	Source() reflect.Value
	GetFieldType(string) reflect.Type
}

func MakeRecord

func MakeRecord(model *Model, _type reflect.Type) ModelRecord

func NewRecord

func NewRecord(model *Model, value reflect.Value) ModelRecord

func NewStructRecord

func NewStructRecord(model *Model, value reflect.Value) ModelRecord

type ModelRecordFieldTypes

type ModelRecordFieldTypes interface {
	GetFieldType(field string) reflect.Type
}

type ModelRecords

type ModelRecords interface {
	GetRecord(int) ModelRecord
	GetRecords() []ModelRecord
	Add(v reflect.Value) ModelRecord
	GetFieldType(string) reflect.Type
	GetFieldAddressType(string) reflect.Type
	IsVariableContainer() bool
	ElemType() reflect.Type
	Len() int
	Source() reflect.Value
	GroupBy(key string) ModelGroupBy
}

func MakeRecords

func MakeRecords(model *Model, _type reflect.Type) ModelRecords

func MakeRecordsWithElem

func MakeRecordsWithElem(model *Model, _type reflect.Type) ModelRecords

use element type to create ModelRecords

func NewRecords

func NewRecords(model *Model, value reflect.Value) ModelRecords

type ModelStructRecord

type ModelStructRecord struct {
	FieldValues        map[string]reflect.Value
	VirtualFieldValues map[string]reflect.Value
	// contains filtered or unexported fields
}

func (*ModelStructRecord) AllField

func (m *ModelStructRecord) AllField() map[string]reflect.Value

func (*ModelStructRecord) Field

func (m *ModelStructRecord) Field(name string) reflect.Value

func (*ModelStructRecord) FieldAddress

func (m *ModelStructRecord) FieldAddress(name string) reflect.Value

func (*ModelStructRecord) GetFieldType

func (m *ModelStructRecord) GetFieldType(name string) reflect.Type

func (*ModelStructRecord) IsVariableContainer

func (m *ModelStructRecord) IsVariableContainer() bool

func (*ModelStructRecord) SetField

func (m *ModelStructRecord) SetField(name string, value reflect.Value)

set field to field value map or virtual field value map but if value is invalid delete it on map

func (*ModelStructRecord) Source

func (m *ModelStructRecord) Source() reflect.Value

type ModelStructRecords

type ModelStructRecords struct {
	Type reflect.Type

	RelationFieldPos       map[string]int
	FieldTypes             map[string]reflect.Type
	FieldValuesList        []map[string]reflect.Value
	VirtualFieldValuesList []map[string]reflect.Value
	// contains filtered or unexported fields
}

func NewStructRecords

func NewStructRecords(model *Model, value reflect.Value) *ModelStructRecords

func (*ModelStructRecords) Add

func (*ModelStructRecords) ElemType

func (m *ModelStructRecords) ElemType() reflect.Type

func (*ModelStructRecords) GetFieldAddressType

func (m *ModelStructRecords) GetFieldAddressType(field string) reflect.Type

func (*ModelStructRecords) GetFieldType

func (m *ModelStructRecords) GetFieldType(field string) reflect.Type

func (*ModelStructRecords) GetRecord

func (m *ModelStructRecords) GetRecord(i int) ModelRecord

func (*ModelStructRecords) GetRecords

func (m *ModelStructRecords) GetRecords() []ModelRecord

func (*ModelStructRecords) GroupBy

func (m *ModelStructRecords) GroupBy(key string) ModelGroupBy

func (*ModelStructRecords) IsVariableContainer

func (m *ModelStructRecords) IsVariableContainer() bool

func (*ModelStructRecords) Len

func (m *ModelStructRecords) Len() int

func (*ModelStructRecords) Source

func (m *ModelStructRecords) Source() reflect.Value

type MySqlDialect

type MySqlDialect struct {
	DefaultDialect
}

func (MySqlDialect) CreateTable

func (dia MySqlDialect) CreateTable(model *Model, foreign map[string]ForeignKey) (execlist []ExecValue)

func (MySqlDialect) HasTable

func (dia MySqlDialect) HasTable(model *Model) ExecValue

func (MySqlDialect) ReplaceExec

func (dia MySqlDialect) ReplaceExec(model *Model, columnValues []ColumnValue) ExecValue

replace will failure when have foreign key

type OneToManyPreload

type OneToManyPreload struct {
	Model          *Model
	SubModel       *Model
	RelationField  Field
	ContainerField Field
}

this is describe one to many relationship with table and its sub table e.g select * from sub_table where sub_table.RelationField = table.id

type OneToOnePreload

type OneToOnePreload struct {
	Model         *Model
	SubModel      *Model
	RelationField Field
	// used to save other table value
	ContainerField Field
}

this is describe one to one relationship with table and its sub table e.g select * from sub_table where sub_table.RelationField = table.id;

type Pair

type Pair struct {
	Main int
	Sub  int
}

type PostgreSqlDialect

type PostgreSqlDialect struct{}

func (PostgreSqlDialect) AddForeignKey

func (dia PostgreSqlDialect) AddForeignKey(model, relationModel *Model, ForeignKeyField Field) ExecValue

func (PostgreSqlDialect) ConditionExec

func (dia PostgreSqlDialect) ConditionExec(search SearchList, limit, offset int, orderBy []Column, groupBy []Column) ExecValue

func (PostgreSqlDialect) CountExec

func (dia PostgreSqlDialect) CountExec(model *Model) ExecValue

func (PostgreSqlDialect) CreateTable

func (dia PostgreSqlDialect) CreateTable(model *Model, foreign map[string]ForeignKey) (execlist []ExecValue)

func (PostgreSqlDialect) DeleteExec

func (dia PostgreSqlDialect) DeleteExec(model *Model) (exec ExecValue)

func (PostgreSqlDialect) DropForeignKey

func (dia PostgreSqlDialect) DropForeignKey(model *Model, ForeignKeyField Field) ExecValue

func (PostgreSqlDialect) DropTable

func (dia PostgreSqlDialect) DropTable(m *Model) ExecValue

func (PostgreSqlDialect) FindExec

func (dia PostgreSqlDialect) FindExec(model *Model, columns []Column, alias string) ExecValue

func (PostgreSqlDialect) HasTable

func (dia PostgreSqlDialect) HasTable(model *Model) ExecValue

func (PostgreSqlDialect) InsertExec

func (dia PostgreSqlDialect) InsertExec(model *Model, columnValues []ColumnValue) ExecValue

func (PostgreSqlDialect) InsertExecutor

func (dia PostgreSqlDialect) InsertExecutor(db Executor, exec ExecValue, debugPrinter func(string, string, error)) (sql.Result, error)

func (PostgreSqlDialect) JoinExec

func (dia PostgreSqlDialect) JoinExec(mainSwap *JoinSwap) ExecValue

func (PostgreSqlDialect) ReplaceExec

func (dia PostgreSqlDialect) ReplaceExec(model *Model, columnValues []ColumnValue) ExecValue

postgres have not replace use ON CONFLICT(%s) replace

func (PostgreSqlDialect) SearchExec

func (dia PostgreSqlDialect) SearchExec(s SearchList) ExecValue

func (PostgreSqlDialect) TemplateExec

func (dia PostgreSqlDialect) TemplateExec(tExec BasicExec, execs map[string]BasicExec) (ExecValue, error)

func (PostgreSqlDialect) UpdateExec

func (dia PostgreSqlDialect) UpdateExec(model *Model, columnValues []ColumnValue) ExecValue

type PreCollectionBrick

type PreCollectionBrick struct {
	Parent *CollectionBrick
	Field  Field
}

type PreJoinSwap

type PreJoinSwap struct {
	Swap    *JoinSwap
	PreSwap *PreJoinSwap
	Model   *Model
	Field   Field
}

type PreToyBrick

type PreToyBrick struct {
	Parent *ToyBrick
	Field  Field
}

type QToSExec

type QToSExec struct {
	DefaultExec
}

when call Query() method, all '?' in query will replace to '$1','$2'...

func (QToSExec) Append

func (e QToSExec) Append(query string, args ...interface{}) ExecValue

go-bug DefaultExec will return ExecValue(DefaultExec), so must to implement this func

func (QToSExec) Query

func (e QToSExec) Query() string

type QueryAction

type QueryAction struct {
	Exec ExecValue

	Error []error
	// contains filtered or unexported fields
}

func (QueryAction) AffectData

func (r QueryAction) AffectData() []int

func (QueryAction) Err

func (r QueryAction) Err() error

func (QueryAction) SetAffectData

func (r QueryAction) SetAffectData(d []int)

func (QueryAction) String

func (r QueryAction) String() string

func (QueryAction) Type

func (r QueryAction) Type() SqlActionType

type RawResult

type RawResult struct {
	ID  int64
	Err error
}

func (RawResult) LastInsertId

func (t RawResult) LastInsertId() (int64, error)

func (RawResult) RowsAffected

func (t RawResult) RowsAffected() (int64, error)

type ReportData

type ReportData struct {
	Depth      int
	AffectData []*AffectNode
	Str        string
}

type Result

type Result struct {
	Records        ModelRecords
	ActionFlow     []SqlAction
	RecordsActions map[int][]int
	Preload        map[string]*Result
	// container is simple object
	SimpleRelation map[string]map[int]int
	// container is slice object
	MultipleRelation map[string]map[int]Pair

	// in many-to-many model, have a middle model query need to record
	MiddleModelPreload map[string]*Result
}

func (*Result) AddRecord

func (r *Result) AddRecord(q SqlAction)

func (*Result) Err

func (r *Result) Err() error

func (*Result) Report

func (r *Result) Report() string

Rename to Log

type ScanField

type ScanField struct {
	// contains filtered or unexported fields
}

type SearchCell

type SearchCell struct {
	Type SearchExpr
	Val  *BrickColumnValue
}

func NewSearchBranch

func NewSearchBranch(op SearchExpr) SearchCell

func NewSearchLeaf

func NewSearchLeaf(op SearchExpr, columnValue *BrickColumnValue) SearchCell

type SearchExpr

type SearchExpr string

func (SearchExpr) IsBranch

func (op SearchExpr) IsBranch() bool

type SearchList

type SearchList []SearchCell

func (SearchList) Condition

func (s SearchList) Condition(columnValue *BrickColumnValue, expr, linkExpr SearchExpr) SearchList

type SearchTree

type SearchTree struct {
	Val   SearchCell
	Left  *SearchTree
	Right *SearchTree
}

func NewSearchTree

func NewSearchTree(val SearchCell) *SearchTree

func (*SearchTree) Fill

func (s *SearchTree) Fill(left, right *SearchTree) *SearchTree

func (*SearchTree) ToStack

func (s *SearchTree) ToStack() SearchList

type SqlAction

type SqlAction interface {
	String() string
	Type() SqlActionType
	AffectData() []int
	SetAffectData([]int)
	Err() error
}

type SqlActionType

type SqlActionType int

type Sqlite3Dialect

type Sqlite3Dialect struct {
	DefaultDialect
}

func (Sqlite3Dialect) CreateTable

func (dia Sqlite3Dialect) CreateTable(model *Model, foreign map[string]ForeignKey) (execlist []ExecValue)

func (Sqlite3Dialect) HasTable

func (dia Sqlite3Dialect) HasTable(model *Model) ExecValue

type Toy

type Toy struct {
	DefaultHandlerChain      map[string]HandlersChain
	DefaultModelHandlerChain map[reflect.Type]map[string]HandlersChain
	ToyKernel
	// contains filtered or unexported fields
}

func Open

func Open(driverName, dataSourceName string) (*Toy, error)

func (*Toy) BelongToBind

func (t *Toy) BelongToBind(model, subModel *Model, containerField, relationField Field) *BelongToPreload

func (*Toy) BelongToPreload

func (t *Toy) BelongToPreload(model *Model, field Field) *BelongToPreload

func (*Toy) Close

func (t *Toy) Close() error

func (*Toy) Join

func (t *Toy) Join(model *Model, field Field) *Join

func (*Toy) ManyToManyPreload

func (t *Toy) ManyToManyPreload(model *Model, field Field, isRight bool) *ManyToManyPreload

func (*Toy) ManyToManyPreloadBind

func (t *Toy) ManyToManyPreloadBind(model, subModel, middleModel *Model, containerField, relationField, subRelationField Field) *ManyToManyPreload

func (*Toy) MiddleModel

func (t *Toy) MiddleModel(v, sv interface{}) *ToyBrick

func (*Toy) Model

func (t *Toy) Model(v interface{}) *ToyBrick

func (*Toy) ModelHandlers

func (t *Toy) ModelHandlers(option string, model *Model) HandlersChain

func (*Toy) OneToManyBind

func (t *Toy) OneToManyBind(model, subModel *Model, containerField, relationField Field) *OneToManyPreload

func (*Toy) OneToManyPreload

func (t *Toy) OneToManyPreload(model *Model, field Field) *OneToManyPreload

func (*Toy) OneToOneBind

func (t *Toy) OneToOneBind(model, subModel *Model, containerField, relationField Field) *OneToOnePreload

func (*Toy) OneToOnePreload

func (t *Toy) OneToOnePreload(model *Model, field Field) *OneToOnePreload

type ToyBrick

type ToyBrick struct {
	Toy *Toy

	MapPreloadBrick map[string]*ToyBrick

	Search SearchList

	OwnOrderBy []int
	OwnGroupBy []int
	OwnSearch  []int

	SwapMap map[string]*JoinSwap
	JoinMap map[string]*Join

	BrickCommon
	// contains filtered or unexported fields
}

func NewToyBrick

func NewToyBrick(toy *Toy, model *Model) *ToyBrick

func (*ToyBrick) Alias

func (t *ToyBrick) Alias(alias string) *ToyBrick

func (*ToyBrick) And

func (t *ToyBrick) And() ToyBrickAnd

func (*ToyBrick) Begin

func (t *ToyBrick) Begin() *ToyBrick

func (*ToyBrick) BindDefaultFields

func (t *ToyBrick) BindDefaultFields(args ...interface{}) *ToyBrick

func (*ToyBrick) BindFields

func (t *ToyBrick) BindFields(mode Mode, args ...interface{}) *ToyBrick

func (*ToyBrick) CleanOwnGroupBy

func (t *ToyBrick) CleanOwnGroupBy() *ToyBrick

func (*ToyBrick) CleanOwnOrderBy

func (t *ToyBrick) CleanOwnOrderBy() *ToyBrick

func (*ToyBrick) CleanOwnSearch

func (t *ToyBrick) CleanOwnSearch() *ToyBrick

func (*ToyBrick) Commit

func (t *ToyBrick) Commit() error

func (*ToyBrick) ConditionExec

func (t *ToyBrick) ConditionExec() ExecValue

func (*ToyBrick) Conditions

func (t *ToyBrick) Conditions(search SearchList) *ToyBrick

func (*ToyBrick) CopyJoin

func (t *ToyBrick) CopyJoin() map[string]*Join

func (*ToyBrick) CopyJoinSwap

func (t *ToyBrick) CopyJoinSwap() map[string]*JoinSwap

func (*ToyBrick) CopyMapPreloadBrick

func (t *ToyBrick) CopyMapPreloadBrick() map[string]*ToyBrick

func (*ToyBrick) CopyStatus

func (t *ToyBrick) CopyStatus(statusBrick *ToyBrick) *ToyBrick

func (*ToyBrick) Count

func (t *ToyBrick) Count() (count int, err error)

func (*ToyBrick) CountExec

func (t *ToyBrick) CountExec() (exec ExecValue)

func (*ToyBrick) CreateTable

func (t *ToyBrick) CreateTable() (*Result, error)

func (*ToyBrick) CreateTableIfNotExist

func (t *ToyBrick) CreateTableIfNotExist() (*Result, error)

func (*ToyBrick) CustomBelongToPreload

func (t *ToyBrick) CustomBelongToPreload(container, relationship interface{}, args ...interface{}) *ToyBrick

func (*ToyBrick) CustomManyToManyPreload

func (t *ToyBrick) CustomManyToManyPreload(middleStruct, container, relation, subRelation interface{}, args ...interface{}) *ToyBrick

func (*ToyBrick) CustomOneToManyPreload

func (t *ToyBrick) CustomOneToManyPreload(container, relationship interface{}, args ...interface{}) *ToyBrick

func (*ToyBrick) CustomOneToOnePreload

func (t *ToyBrick) CustomOneToOnePreload(container, relationship interface{}, args ...interface{}) *ToyBrick

func (*ToyBrick) Debug

func (t *ToyBrick) Debug() *ToyBrick

func (*ToyBrick) Delete

func (t *ToyBrick) Delete(v interface{}) (*Result, error)

func (*ToyBrick) DeleteExec

func (t *ToyBrick) DeleteExec() ExecValue

func (*ToyBrick) DeleteWithConditions

func (t *ToyBrick) DeleteWithConditions() (*Result, error)

func (*ToyBrick) DropTable

func (t *ToyBrick) DropTable() (*Result, error)

func (*ToyBrick) DropTableIfExist

func (t *ToyBrick) DropTableIfExist() (*Result, error)

func (*ToyBrick) Enter

func (t *ToyBrick) Enter() *ToyBrick

return it parent ToyBrick it will panic when the parent ToyBrick is nil

func (*ToyBrick) Exec

func (t *ToyBrick) Exec(exec ExecValue) (result sql.Result, err error)

func (*ToyBrick) Find

func (t *ToyBrick) Find(v interface{}) (*Result, error)

func (*ToyBrick) FindExec

func (t *ToyBrick) FindExec(columns []Column) ExecValue

func (*ToyBrick) GetContext

func (t *ToyBrick) GetContext(option string, records ModelRecords) *Context

func (*ToyBrick) GroupBy

func (t *ToyBrick) GroupBy(vList ...interface{}) *ToyBrick

func (*ToyBrick) HasTable

func (t *ToyBrick) HasTable() (b bool, err error)

func (*ToyBrick) IgnoreMode

func (t *ToyBrick) IgnoreMode(s Mode, ignore IgnoreMode) *ToyBrick

func (*ToyBrick) Insert

func (t *ToyBrick) Insert(v interface{}) (*Result, error)

insert can receive three type data struct map[offset]interface{} map[int]interface{} insert is difficult that have preload data

func (*ToyBrick) InsertExec

func (t *ToyBrick) InsertExec(record ModelRecord) ExecValue

func (*ToyBrick) Join

func (t *ToyBrick) Join(fv interface{}) *ToyBrick

use join to association query

func (*ToyBrick) Limit

func (t *ToyBrick) Limit(i int) *ToyBrick

func (*ToyBrick) Offset

func (t *ToyBrick) Offset(i int) *ToyBrick

func (*ToyBrick) Or

func (t *ToyBrick) Or() ToyBrickOr

func (*ToyBrick) OrderBy

func (t *ToyBrick) OrderBy(vList ...interface{}) *ToyBrick

func (*ToyBrick) Preload

func (t *ToyBrick) Preload(fv interface{}) *ToyBrick

return

func (*ToyBrick) Prepare

func (t *ToyBrick) Prepare(query string) (*sql.Stmt, error)

func (*ToyBrick) Query

func (t *ToyBrick) Query(exec ExecValue) (rows *sql.Rows, err error)

func (*ToyBrick) QueryRow

func (t *ToyBrick) QueryRow(exec ExecValue) (row *sql.Row)

func (*ToyBrick) ReplaceExec

func (t *ToyBrick) ReplaceExec(record ModelRecord) ExecValue

func (*ToyBrick) RightValuePreload

func (t *ToyBrick) RightValuePreload(fv interface{}) *ToyBrick

this module is get preload which is right middle field name in many-to-many mode it only use for sub model type is same with main model type e.g

User{
    ID int `toyorm:"primary key"`
    Friend []User
}

now the main model middle field name is L_UserID, sub model middle field name is R_UserID if you want to get preload with main model middle field name == R_UserID use RightValuePreload

func (*ToyBrick) Rollback

func (t *ToyBrick) Rollback() error

func (*ToyBrick) Save

func (t *ToyBrick) Save(v interface{}) (*Result, error)

func (*ToyBrick) Scope

func (t *ToyBrick) Scope(fn func(*ToyBrick) *ToyBrick) *ToyBrick

func (*ToyBrick) Swap

func (t *ToyBrick) Swap() *ToyBrick

func (*ToyBrick) Template

func (t *ToyBrick) Template(temp string, args ...interface{}) *ToyBrick

func (*ToyBrick) Update

func (t *ToyBrick) Update(v interface{}) (*Result, error)

func (*ToyBrick) UpdateExec

func (t *ToyBrick) UpdateExec(record ModelRecord) ExecValue

func (*ToyBrick) Where

func (t *ToyBrick) Where(expr SearchExpr, key interface{}, v ...interface{}) *ToyBrick

where will clean old condition

type ToyBrickAnd

type ToyBrickAnd struct {
	Brick *ToyBrick
}

func (ToyBrickAnd) Condition

func (t ToyBrickAnd) Condition(expr SearchExpr, key interface{}, v ...interface{}) *ToyBrick

func (ToyBrickAnd) Conditions

func (t ToyBrickAnd) Conditions(search SearchList) *ToyBrick

type ToyBrickOr

type ToyBrickOr struct {
	Brick *ToyBrick
}

func (ToyBrickOr) Condition

func (t ToyBrickOr) Condition(expr SearchExpr, key interface{}, v ...interface{}) *ToyBrick

func (ToyBrickOr) Conditions

func (t ToyBrickOr) Conditions(search SearchList) *ToyBrick

type ToyCollection

type ToyCollection struct {
	DefaultHandlerChain      map[string]CollectionHandlersChain
	DefaultModelHandlerChain map[reflect.Type]map[string]CollectionHandlersChain
	ToyKernel
	// contains filtered or unexported fields
}

func OpenCollection

func OpenCollection(driverName string, dataSourceName ...string) (*ToyCollection, error)

func (*ToyCollection) BelongToBind

func (t *ToyCollection) BelongToBind(model, subModel *Model, containerField, relationField Field) *BelongToPreload

func (*ToyCollection) BelongToPreload

func (t *ToyCollection) BelongToPreload(model *Model, field Field) *BelongToPreload

func (*ToyCollection) Close

func (t *ToyCollection) Close() error

func (*ToyCollection) GetMiddleModel

func (t *ToyCollection) GetMiddleModel(_type reflect.Type) *Model

func (*ToyCollection) ManyToManyPreload

func (t *ToyCollection) ManyToManyPreload(model *Model, field Field, isRight bool) *ManyToManyPreload

func (*ToyCollection) ManyToManyPreloadBind

func (t *ToyCollection) ManyToManyPreloadBind(model, subModel, middleModel *Model, containerField, relationField, subRelationField Field) *ManyToManyPreload

func (*ToyCollection) MiddleModel

func (t *ToyCollection) MiddleModel(v, sv interface{}) *CollectionBrick

func (*ToyCollection) Model

func (t *ToyCollection) Model(v interface{}) *CollectionBrick

func (*ToyCollection) ModelHandlers

func (t *ToyCollection) ModelHandlers(option string, model *Model) CollectionHandlersChain

func (*ToyCollection) OneToManyBind

func (t *ToyCollection) OneToManyBind(model, subModel *Model, containerField, relationField Field) *OneToManyPreload

func (*ToyCollection) OneToManyPreload

func (t *ToyCollection) OneToManyPreload(model *Model, field Field) *OneToManyPreload

func (*ToyCollection) OneToOneBind

func (t *ToyCollection) OneToOneBind(model, subModel *Model, containerField, relationField Field) *OneToOnePreload

func (*ToyCollection) OneToOnePreload

func (t *ToyCollection) OneToOnePreload(model *Model, field Field) *OneToOnePreload

func (*ToyCollection) SetModelHandlers

func (t *ToyCollection) SetModelHandlers(option string, model *Model, handlers CollectionHandlersChain)

type ToyKernel

type ToyKernel struct {
	CacheModels              map[reflect.Type]*Model
	CacheMiddleModels        map[reflect.Type]*Model
	CacheReverseMiddleModels map[reflect.Type]*Model

	// map[model][container_field_name]
	Dialect Dialect
	Logger  io.Writer
	// contains filtered or unexported fields
}

func (*ToyKernel) GetMiddleModel

func (t *ToyKernel) GetMiddleModel(_type reflect.Type) *Model

func (*ToyKernel) GetModel

func (t *ToyKernel) GetModel(_type reflect.Type) *Model

TODO testing thread safe? if not add lock

func (*ToyKernel) SetDebug

func (t *ToyKernel) SetDebug(debug bool)

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL