A code generator base on GORM

Related tags

ORM golang generator gorm
Overview

GORM/GEN

GoVersion Release Go.Dev reference Go Report Card MIT license OpenIssue ClosedIssue TODOs

The code generator base on GORM, aims to be developer friendly.

Overview

  • CRUD or DIY query method code generation
  • Auto migration from database to code
  • Transactions, Nested Transactions, Save Point, RollbackTo to Saved Point
  • Competely compatible with GORM
  • Developer Friendly

Contents

Installation

To install Gen package, you need to install Go and set your Go workspace first.

1.The first need Go installed(version 1.14+ is required), then you can use the below Go command to install Gen.

go get -u gorm.io/gen

2.Import it in your code:

import "gorm.io/gen"

Quick start

# assume the following code in generate.go file
$ cat generate.go
package main

import "gorm.io/gen"

// generate code
func main() {
    // specify the output directory (default: "./query")
    g := gen.NewGenerator(gen.Config{OutPath: "../dal/query"})
  
    // reuse the database connection in Project or create a connection here
    // db, _ := gorm.Open(mysql.Open("root:@(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"))
    g.UseDB(db)
  
    // apply basic crud api on structs or table models which is specified by table name with function
    // GenerateModel/GenerateModelAs. And generator will generate table models' code when calling Excute.
    g.ApplyBasic(model.User{}, g.GenerateModel("company"), g.GenerateModelAs("people", "Person"),)
    
    // apply diy interfaces on structs or table models
    g.ApplyInterface(func(method model.Method) {}, model.User{}, g.GenerateModel("company"))

    // execute the action of code generation
    g.Execute()
}

Project Directory

Here is a template for best practices:

demo
├── cmd
│   └── generate
│       └── generate.go # execute it will generate codes
├── dal
│   ├── dal.go # create connections with database server here
│   ├── model
│   │   ├── method.go # DIY method interfaces
│   │   └── model.go  # store struct which corresponding to the database table
│   └── query  # generated code's directory
│       └── gorm_generated.go # generated code
├── biz
│   └── query.go # call function in dal/gorm_generated.go and query databases
├── config
│   └── config.go # DSN for database server
├── generate.sh # a shell to execute cmd/generate
├── go.mod
├── go.sum
└── main.go

API Examples

Field Expression

Create Field

Actually, you're not supposed to create a new field variable, cause it will be accomplished in generated code.

Field Type Detail Type Crerate Function Supported Query Method
generic field NewField IsNull/IsNotNull/Count
int int/int8/.../int64 NewInt/NewInt8/.../NewInt64 Eq/Neq/Gt/Gte/Lt/Lte/In/NotIn/Between/NotBetween/Like/NotLike/Add/Sub/Mul/Div/Mod/FloorDiv/RightShift/LeftShift/BitXor/BitAnd/BitOr/BitFlip
uint uint/uint8/.../uint64 NewUint/NewUint8/.../NewUint64 same with int
float float32/float64 NewFloat32/NewFloat64 Eq/Neq/Gt/Gte/Lt/Lte/In/NotIn/Between/NotBetween/Like/NotLike/Add/Sub/Mul/Div/FloorDiv
string string/[]byte NewString/NewBytes Eq/Neq/Gt/Gte/Lt/Lte/Between/NotBetween/In(val/NotIn(val/Like/NotLike/Regexp/NotRegxp
bool bool NewBool Not/Is/And/Or/Xor/BitXor/BitAnd/BitOr
time time.Time NewTime Eq/Neq/Gt/Gte/Lt/Lte/Between/NotBetween/In/NotIn/Add/Sub

Create field examples:

import "gorm.io/gen/field"

// create a new generic field map to `generic_a`
a := field.NewField("table_name", "generic_a")

// create a field map to `id`
i := field.NewInt("user", "id")

// create a field map to `address`
s := field.NewString("user", "address")

// create a field map to `create_time`
t := field.NewTime("user", "create_time")

CRUD API

Here is a basic struct user and struct DB.

// generated code
// generated code
// generated code
package query

import "gorm.io/gen"

// struct map to table `users` 
type user struct {
    gen.DO
    ID       field.Uint
    Name     field.String
    Age      field.Int
    Address  field.Field
    Birthday field.Time
}

// struct collection
type DB struct {
    db       *gorm.DB
    User     *user
}

Create

Create record
// u refer to query.user
user := model.User{Name: "Modi", Age: 18, Birthday: time.Now()}

u := query.Query.User
err := u.Create(&user) // pass pointer of data to Create

err // returns error
Create record with selected fields

Create a record and assgin a value to the fields specified.

u := query.Query.User
u.Select(u.Name, u.Age).Create(&user)
// INSERT INTO `users` (`name`,`age`) VALUES ("modi", 18)

Create a record and ignore the values for fields passed to omit

u := query.Query.User
u.Omit(u.Name, u.Age).Create(&user)
// INSERT INTO `users` (`Address`, `Birthday`) VALUES ("2021-08-17 20:54:12.000", 18)
Batch Insert

To efficiently insert large number of records, pass a slice to the Create method. GORM will generate a single SQL statement to insert all the data and backfill primary key values.

var users = []model.User{{Name: "modi"}, {Name: "zhangqiang"}, {Name: "songyuan"}}
query.Query.User.Create(&users)

for _, user := range users {
    user.ID // 1,2,3
}

You can specify batch size when creating with CreateInBatches, e.g:

var users = []User{{Name: "modi_1"}, ...., {Name: "modi_10000"}}

// batch size 100
query.Query.User.CreateInBatches(users, 100)

It will works if you set CreateBatchSize in gorm.Config / gorm.Session

db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
    CreateBatchSize: 1000,
})
// OR
db = db.Session(&gorm.Session{CreateBatchSize: 1000})

u := query.NewUser(db)

var users = []User{{Name: "modi_1"}, ...., {Name: "modi_5000"}}

u.Create(&users)
// INSERT INTO users xxx (5 batches)

Query

Retrieving a single object

Generated code provides First, Take, Last methods to retrieve a single object from the database, it adds LIMIT 1 condition when querying the database, and it will return the error ErrRecordNotFound if no record is found.

u := query.Query.User

// Get the first record ordered by primary key
user, err := u.First()
// SELECT * FROM users ORDER BY id LIMIT 1;

// Get one record, no specified order
user, err := u.Take()
// SELECT * FROM users LIMIT 1;

// Get last record, ordered by primary key desc
user, err := u.Last()
// SELECT * FROM users ORDER BY id DESC LIMIT 1;

// check error ErrRecordNotFound
errors.Is(err, gorm.ErrRecordNotFound)
Retrieving objects with primary key
u := query.Query.User

user, err := u.Where(u.ID.Eq(10)).First()
// SELECT * FROM users WHERE id = 10;

users, err := u.Where(u.ID.In(1,2,3)).Find()
// SELECT * FROM users WHERE id IN (1,2,3);

If the primary key is a string (for example, like a uuid), the query will be written as follows:

user, err := u.Where(u.ID.Eq("1b74413f-f3b8-409f-ac47-e8c062e3472a")).First()
// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";
Retrieving all objects
u := query.Query.User

// Get all records
users, err := u.Find()
// SELECT * FROM users;
Conditions
String Conditions
'modi'; // IN users, err := u.Where(u.Name.In("modi", "zhangqiang")).Find() // SELECT * FROM users WHERE name IN ('modi','zhangqiang'); // LIKE users, err := u.Where(u.Name.Like("%modi%")).Find() // SELECT * FROM users WHERE name LIKE '%modi%'; // AND users, err := u.Where(u.Name.Eq("modi"), u.Age.Gte(17)).Find() // SELECT * FROM users WHERE name = 'modi' AND age >= 17; // Time users, err := u.Where(u.Birthday.Gt(birthTime).Find() // SELECT * FROM users WHERE birthday > '2000-01-01 00:00:00'; // BETWEEN users, err := u.Where(u.Birthday.Between(lastWeek, today)).Find() // SELECT * FROM users WHERE birthday BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00'; ">
u := query.Query.User

// Get first matched record
user, err := u.Where(u.Name.Eq("modi")).First()
// SELECT * FROM users WHERE name = 'modi' ORDER BY id LIMIT 1;

// Get all matched records
users, err := u.Where(u.Name.Neq("modi")).Find()
// SELECT * FROM users WHERE name <> 'modi';

// IN
users, err := u.Where(u.Name.In("modi", "zhangqiang")).Find()
// SELECT * FROM users WHERE name IN ('modi','zhangqiang');

// LIKE
users, err := u.Where(u.Name.Like("%modi%")).Find()
// SELECT * FROM users WHERE name LIKE '%modi%';

// AND
users, err := u.Where(u.Name.Eq("modi"), u.Age.Gte(17)).Find()
// SELECT * FROM users WHERE name = 'modi' AND age >= 17;

// Time
users, err := u.Where(u.Birthday.Gt(birthTime).Find()
// SELECT * FROM users WHERE birthday > '2000-01-01 00:00:00';

// BETWEEN
users, err := u.Where(u.Birthday.Between(lastWeek, today)).Find()
// SELECT * FROM users WHERE birthday BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';
Inline Condition
"modi" AND age > 17; ">
u := query.Query.User

// Get by primary key if it were a non-integer type
user, err := u.Where(u.ID.Eq("string_primary_key")).First()
// SELECT * FROM users WHERE id = 'string_primary_key';

// Plain SQL
users, err := u.Where(u.Name.Eq("modi")).Find()
// SELECT * FROM users WHERE name = "modi";

users, err := u.Where(u.Name.Neq("modi"), u.Age.Gt(17)).Find()
// SELECT * FROM users WHERE name <> "modi" AND age > 17;
Not Conditions

Build NOT conditions, works similar to Where

u := query.Query.User

user, err := u.Not(u.Name.Eq("modi")).First()
// SELECT * FROM users WHERE NOT name = "modi" ORDER BY id LIMIT 1;

// Not In
users, err := u.Not(u.Name.In("modi", "zhangqiang")).Find()
// SELECT * FROM users WHERE name NOT IN ("modi", "zhangqiang");

// Not In slice of primary keys
user, err := u.Not(u.ID.In(1,2,3)).First()
// SELECT * FROM users WHERE id NOT IN (1,2,3) ORDER BY id LIMIT 1;
Or Conditions
u := query.Query.User

users, err := u.Where(u.Role.Eq("admin")).Or(u.Role.Eq("super_admin")).Find()
// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';
Group Conditions

Easier to write complicated SQL query with Group Conditions

p := query.Query.Pizza

pizzas, err := p.Where(
    p.Where(p.Pizza.Eq("pepperoni")).Where(p.Where(p.Size.Eq("small")).Or(p.Size.Eq("medium"))),
).Or(
    p.Where(p.Pizza.Eq("hawaiian")).Where(p.Size.Eq("xlarge")),
).Find()

// SELECT * FROM `pizzas` WHERE (pizza = "pepperoni" AND (size = "small" OR size = "medium")) OR (pizza = "hawaiian" AND size = "xlarge")
Selecting Specific Fields

Select allows you to specify the fields that you want to retrieve from database. Otherwise, GORM will select all fields by default.

u := query.Query.User

users, err := u.Select(u.Name, u.Age).Find()
// SELECT name, age FROM users;

u.Select(u.Age.Avg()).Rows()
// SELECT Avg(age) FROM users;
Order

Specify order when retrieving records from the database

u := query.Query.User

users, err := u.Order(u.Age.Desc(), u.Name).Find()
// SELECT * FROM users ORDER BY age DESC, name;

// Multiple orders
users, err := u.Order(u.Age.Desc()).Order(u.Name).Find()
// SELECT * FROM users ORDER BY age DESC, name;
Limit & Offset

Limit specify the max number of records to retrieve Offset specify the number of records to skip before starting to return the records

u := query.Query.User

urers, err := u.Limit(3).Find()
// SELECT * FROM users LIMIT 3;

// Cancel limit condition with -1
users, err := u.Limit(10).Limit(-1).Find()
// SELECT * FROM users;

users, err := u.Offset(3).Find()
// SELECT * FROM users OFFSET 3;

users, err := u.Limit(10).Offset(5).Find()
// SELECT * FROM users OFFSET 5 LIMIT 10;

// Cancel offset condition with -1
users, err := u.Offset(10).Offset(-1).Find()
// SELECT * FROM users;
Group By & Having
u := query.Query.User

type Result struct {
    Date  time.Time
    Total int
}

var result Result

err := u.Select(u.Name, u.Age.Sum().As("total")).Where(u.Name.Like("%modi%")).Group(u.Name).Scan(&result)
// SELECT name, sum(age) as total FROM `users` WHERE name LIKE "group%" GROUP BY `name`

err := u.Select(u.Name, u.Age.Sum().As("total")).Group(u.Name).Having(u.Name.Eq("group")).Scan(&result)
// SELECT name, sum(age) as total FROM `users` GROUP BY `name` HAVING name = "group"

rows, err := u.Select(u.Birthday.As("date"), u.Age.Sum().As("total")).Group(u.Birthday).Rows()
for rows.Next() {
  ...
}

o := query.Query.Order

rows, err := o.Select(o.CreateAt.Date().As("date"), o.Amount.Sum().As("total")).Group(o.CreateAt.Date()).Having(u.Amount.Sum().Gt(100)).Rows()
for rows.Next() {
  ...
}

var results []Result

o.Select(o.CreateAt.Date().As("date"), o.Amount.Sum().As("total")).Group(o.CreateAt.Date()).Having(u.Amount.Sum().Gt(100)).Scan(&results)
Distinct

Selecting distinct values from the model

u := query.Query.User

users, err := u.Distinct(u.Name, u.Age).Order(u.Name, u.Age.Desc()).Find()

Distinct works with Pluck and Count too

Joins

Specify Joins conditions

u := query.Query.User
e := query.Query.Email
c := query.Query.CreditCard

type Result struct {
    Name  string
    Email string
}

var result Result

err := u.Select(u.Name, e.Email).LeftJoin(e, e.UserId.EqCol(u.ID)).Scan(&result)
// SELECT users.name, emails.email FROM `users` left join emails on emails.user_id = users.id

rows, err := u.Select(u.Name, e.Email).LeftJoin(e, e.UserId.EqCol(u.ID)).Rows()
for rows.Next() {
  ...
}

var results []Result

err := u.Select(u.Name, e.Email).LeftJoin(e, e.UserId.EqCol(u.ID)).Scan(&results)

// multiple joins with parameter
users := u.Join(e, e.UserId.EqCol(u.id), e.Email.Eq("[email protected]")).Join(c, c.UserId.EqCol(u.ID)).Where(c.Number.Eq("411111111111")).Find()
SubQuery

A subquery can be nested within a query, GEN can generate subquery when using a Dao object as param

(SELECT AVG(amount) FROM "orders"); subQuery := u.Select(u.Age.Avg()).Where(u.Name.Like("name%")) users, err := u.Select(u.Age.Avg().As("avgage")).Group(u.Name).Having(gen.Gt(u.Age.Avg(), subQuery).Find() // SELECT AVG(age) as avgage FROM `users` GROUP BY `name` HAVING AVG(age) > (SELECT AVG(age) FROM `users` WHERE name LIKE "name%") ">
o := query.Query.Order
u := query.Query.User

orders, err := o.Where(gen.Gt(o.Amount, o.Select(u.Amount.Avg())).Find()
// SELECT * FROM "orders" WHERE amount > (SELECT AVG(amount) FROM "orders");

subQuery := u.Select(u.Age.Avg()).Where(u.Name.Like("name%"))
users, err := u.Select(u.Age.Avg().As("avgage")).Group(u.Name).Having(gen.Gt(u.Age.Avg(), subQuery).Find()
// SELECT AVG(age) as avgage FROM `users` GROUP BY `name` HAVING AVG(age) > (SELECT AVG(age) FROM `users` WHERE name LIKE "name%")
From SubQuery

GORM allows you using subquery in FROM clause with method Table, for example:

u := query.Query.User
p := query.Query.Pet

users, err := gen.Table(u.Select(u.Name, u.Age).As("u")).Where(u.Age.Eq(18)).Find()
// SELECT * FROM (SELECT `name`,`age` FROM `users`) as u WHERE `age` = 18

subQuery1 := u.Select(u.Name)
subQuery2 := p.Select(p.Name)
users, err := gen.Table(subQuery1.As("u"), subQuery2.As("p")).Find()
db.Table("(?) as u, (?) as p", subQuery1, subQuery2).Find(&User{})
// SELECT * FROM (SELECT `name` FROM `users`) as u, (SELECT `name` FROM `pets`) as p
Update from SubQuery

Update a table by using SubQuery

u := query.Query.User
c := query.Query.Company

u.Update(u.CompanyName, c.Select(c.Name).Where(c.ID.EqCol(u.CompanyId)))
// UPDATE "users" SET "company_name" = (SELECT name FROM companies WHERE companies.id = users.company_id);

u.Where(u.Name.Eq("modi")).Update(u.CompanyName, c.Select(c.Name).Where(c.ID.EqCol(u.CompanyId)))
Advanced Query
Iteration

GEN supports iterating through Rows

rows, err := query.Query.User.Where(u.Name.Eq("modi")).Rows()
defer rows.Close()

for rows.Next() {
    var user User
    // ScanRows is a method of `gorm.DB`, it can be used to scan a row into a struct
    db.ScanRows(rows, &user)

    // do something
}
FindInBatches

Query and process records in batch

u := query.Query.User

// batch size 100
err := u.Where(u.ID.Gt(9)).FindInBatches(&results, 100, func(tx gen.Dao, batch int) error {
    for _, result := range results {
      // batch processing found records
    }
  
    // build a new `u` to use it's api
    // queryUsery := query.NewUser(tx.UnderlyingDB())

    tx.Save(&results)

    batch // Batch 1, 2, 3

    // returns error will stop future batches
    return nil
})
Pluck

Query single column from database and scan into a slice, if you want to query multiple columns, use Select with Scan instead

u := query.Query.User

var ages []int64
u.Pluck(u.Age, &ages)

var names []string
u.Pluck(u.Name, &names)

// Distinct Pluck
u.Distinct().Pluck(u.Name, &names)
// SELECT DISTINCT `name` FROM `users`

// Requesting more than one column, use `Scan` or `Find` like this:
db.Select(u.Name, u.Age).Scan(&users)
users, err := db.Select(u.Name, u.Age).Find()
Scopes

Scopes allows you to specify commonly-used queries which can be referenced as method calls

o := query.Query.Order

func AmountGreaterThan1000(tx gen.Dao) gen.Dao {
    return tx.Where(o.Amount.Gt(1000))
}

func PaidWithCreditCard(tx gen.Dao) gen.Dao {
    return tx.Where(o.PayModeSign.Eq("C"))
}

func PaidWithCod(tx gen.Dao) gen.Dao {
    return tx.Where(o.PayModeSign.Eq("C"))
}

func OrderStatus(status []string) func (tx gen.Dao) gen.Dao {
    return func (tx gen.Dao) gen.Dao {
      return tx.Where(o.Status.In(status...))
    }
}

orders, err := o.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find()
// Find all credit card orders and amount greater than 1000

orders, err := o.Scopes(AmountGreaterThan1000, PaidWithCod).Find()
// Find all COD orders and amount greater than 1000

orders, err := o.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find()
// Find all paid, shipped orders that amount greater than 1000
Count

Get matched records count

u := query.Query.User

count, err := u.Where(u.Name.Eq("modi")).Or(u.Name.Eq("zhangqiang")).Count()
// SELECT count(1) FROM users WHERE name = 'modi' OR name = 'zhangqiang'

count, err := u.Where(u.Name.Eq("modi")).Count()
// SELECT count(1) FROM users WHERE name = 'modi'; (count)

// Count with Distinct
u.Distinct(u.Name).Count()
// SELECT COUNT(DISTINCT(`name`)) FROM `users`

Update

Update single column

When updating a single column with Update, it needs to have any conditions or it will raise error ErrMissingWhereClause, for example:

u := query.Query.User

// Update with conditions
u.Where(u.Activate.Is(true)).Update(u.Name, "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;

// Update with conditions
u.Where(u.Activate.Is(true)).Update(u.Age, u.Age.Add(1))
// UPDATE users SET age=age+1, updated_at='2013-11-17 21:34:10' WHERE active=true;
Updates multiple columns

Updates supports update with struct or map[string]interface{}, when updating with struct it will only update non-zero fields by default

u := query.Query.User

// Update attributes with `map`
u).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

NOTE When update with struct, GEN will only update non-zero fields, you might want to use map to update attributes or use Select to specify fields to update

Update selected fields

If you want to update selected fields or ignore some fields when updating, you can use Select, Omit

u := query.Query.User

// Select with Map
// User's ID is `111`:
u.Select(u.Name).Where(u.ID.Eq(111)).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello' WHERE id=111;

u.Omit(u.Name).Where(u.ID.Eq(111)).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

Delete

Delete record
e := query.Query.Email

// Email's ID is `10`
e.Where(e.ID.Eq(10)).Delete()
// DELETE from emails where id = 10;

// Delete with additional conditions
e.Where(e.ID.Eq(10), e.Name.Eq("modi")).Delete()
// DELETE from emails where id = 10 AND name = "modi";
Delete with primary key

GEN allows to delete objects using primary key(s) with inline condition, it works with numbers.

u.Where(u.ID.In(1,2,3)).Delete()
// DELETE FROM users WHERE id IN (1,2,3);
Batch Delete

The specified value has no primary value, GEN will perform a batch delete, it will delete all matched records

e := query.Query.Email

err := e.Where(e.Name.Like("%modi%")).Delete()
// DELETE from emails where email LIKE "%modi%";
Soft Delete

If your model includes a gorm.DeletedAt field (which is included in gorm.Model), it will get soft delete ability automatically!

When calling Delete, the record WON’T be removed from the database, but GORM will set the DeletedAt‘s value to the current time, and the data is not findable with normal Query methods anymore.

// Batch Delete
err := u.Where(u.Age.Eq(20)).Delete()
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;

// Soft deleted records will be ignored when querying
users, err := u.Where(u.Age.Eq(20)).Find()
// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;

If you don’t want to include gorm.Model, you can enable the soft delete feature like:

type User struct {
    ID      int
    Deleted gorm.DeletedAt
    Name    string
}
Find soft deleted records

You can find soft deleted records with Unscoped

users, err := db.Unscoped().Where(u.Age.Eq(20)).Find()
// SELECT * FROM users WHERE age = 20;
Delete permanently

You can delete matched records permanently with Unscoped

o.Unscoped().Where(o.ID.Eq(10)).Delete()
// DELETE FROM orders WHERE id=10;

DIY method

Method interface

Method interface is an abstraction of query methods, all functions it contains are query methods and above comments describe the specific query conditions or logic. SQL supports simple where query or execute raw SQL. Simple query conditions wrapped by where(), and raw SQL wrapped by sql()(not required)

type Method interface {
    // where("[email protected] and [email protected]")
    SimpleFindByNameAndAge(name string, age int) (gen.T, error)
    
    // sql(select * from users where [email protected])
    FindUserToMap(id int) (gen.M, error)
    
    // insert into users (name,age) values (@name,@age)
    InsertValue(age int, name string) error
}

Return values must contains less than 1 gen.T/gen.M and less than 1 error. You can also use bulitin type (like string/ int) as the return parameter,gen.T represents return a single result struct's pointer, []gen.T represents return an array of result structs' pointer,

Syntax of template
placeholder
  • gen.T represents specified struct or table
  • gen.M represents map[string]interface
  • @@table represents table's name (if method's parameter doesn't contains variable table, GEN will generate table from model struct)
  • @@ represents column's name or table's name
  • @ represents normal query variable
template

Logical operations must be wrapped in {{}},and end must used {{end}}, All templates support nesting

  • if/else if/else the condition accept a bool parameter or operation expression which conforms to Golang syntax.
  • where The where clause will be inserted only if the child elements return something. The key word and or or in front of clause will be removed. And and will be added automatically when there is no junction keyword between query condition clause.
  • Set The set clause will be inserted only if the child elements return something. The , in front of columns array will be removed.And , will be added automatically when there is no junction keyword between query coulmns.
  • ... Coming soon
If clause
{{if cond1}}
    // do something here
{{else if cond2}}
    // do something here
{{else}}
    // do something here
{{end}}

Use case in raw SQL:

// select * from users where {{if name !=""}} [email protected]{{end}}
methond(name string) (gen.T,error) 

Use case in raw SQL template:

30}} status="middle-ager" {{else if age>18}} status="younger" {{else}} {{if sex=="male"}} status="boys" {{else}} status="girls" {{end}} {{end}} ">
select * from @@table where
{{if age>60}}
    status="older"
{{else if age>30}}
    status="middle-ager"
{{else if age>18}}
    status="younger"
{{else}}
    {{if sex=="male"}}
        status="boys"
    {{else}}
        status="girls"
    {{end}}
{{end}}
Where clause
{{where}}
    // do something here
{{end}}

Use case in raw SQL

// select * from {{where}}[email protected]{{end}}
methond(id int) error

Use case in raw SQL template

select * from @@table 
{{where}}
    {{if cond}}id=@id {{end}}
    {{if name != ""}}@@key=@value{{end}}
{{end}}
Set clause
{{set}}
    // sepecify update expression here
{{end}}

Use case in raw SQL

// update users {{set}}[email protected]{{end}}
methond() error

Use case in raw SQL template

0}} [email protected] {{end}} {{end}} where [email protected] ">
update @@table 
{{set}}
    {{if name!=""}} name=@name {{end}}
    {{if age>0}} age=@age {{end}}
{{end}}
where id=@id
Method interface example
0 // {{if cond}}[email protected] {{end}} // {{if key!="" && value != ""}} or @@[email protected]{{end}} // {{end}} FindByIDOrCustom(cond bool, id int, key, value string) ([]gen.T, error) // update @@table // {{set}} // update_time=now() // {{if name != ""}} // [email protected] // {{end}} // {{end}} // {{where}} // [email protected] // {{end}} UpdateName(name string, id int) error } ">
type Method interface {
    // Where("[email protected] and [email protected]")
    SimpleFindByNameAndAge(name string, age int) (gen.T, error)
    
    // select * from users where [email protected]
    FindUserToMap(id int) (gen.M, error)
    
    // sql(insert into @@table (name,age) values (@name,@age) )
    InsertValue(age int, name string) error
    
    // select name from @@table where [email protected]
    FindNameById(id int) string
    
    // select * from @@table
    //  {{where}}
    //      id>0
    //      {{if cond}}[email protected] {{end}}
    //      {{if key!="" && value != ""}} or @@[email protected]{{end}}
    //  {{end}}
    FindByIDOrCustom(cond bool, id int, key, value string) ([]gen.T, error)
    
    // update @@table
    //  {{set}}
    //      update_time=now()
    //      {{if name != ""}}
    //          [email protected]
    //      {{end}}
    //  {{end}}
    //  {{where}}
    //      [email protected]
    //  {{end}}
    UpdateName(name string, id int) error
}

Smart select fields

GEN allows select specific fields with Select, if you often use this in your application, maybe you want to define a smaller struct for API usage which can select specific fields automatically, for example:

type User struct {
  ID     uint
  Name   string
  Age    int
  Gender string
  // hundreds of fields
}

type APIUser struct {
  ID   uint
  Name string
}

type Method interface{
    // select * from user
    FindSome() ([]APIUser, error)
}

apiusers, err := u.Limit(10).FindSome()
// SELECT `id`, `name` FROM `users` LIMIT 10

Advanced Topics

Hints

Optimizer hints allow to control the query optimizer to choose a certain query execution plan, GORM supports it with gorm.io/hints, e.g:

import "gorm.io/hints"

u := query.Query.User

users, err := u.Hints(hints.New("MAX_EXECUTION_TIME(10000)")).Find()
// SELECT * /*+ MAX_EXECUTION_TIME(10000) */ FROM `users`

Index hints allow passing index hints to the database in case the query planner gets confused.

import "gorm.io/hints"

u := query.Query.User

users, err := u.Hints(hints.UseIndex("idx_user_name")).Find()
// SELECT * FROM `users` USE INDEX (`idx_user_name`)

users, err := u.Hints(hints.ForceIndex("idx_user_name", "idx_user_id").ForJoin()).Find()
// SELECT * FROM `users` FORCE INDEX FOR JOIN (`idx_user_name`,`idx_user_id`)"

Contributing

You can help to deliver a better GORM/GEN

License

Released under the MIT License

Comments
  • DateFormat转换出现?占位符,参数没有赋值

    DateFormat转换出现?占位符,参数没有赋值

    GORM Playground Link

    场景,按照订购日期cdate、单据状态state分组,汇总单据总数及总金额,sql如下:

    SELECT
    	count( 1 ) AS num,
    	sum( amount ) AS amount,
    	`status`,
    	DATE_FORMAT( cdate, '%Y-%m-%d' ) AS cdate 
    FROM
    	s3_order_bill 
    GROUP BY
    	DATE_FORMAT( cdate, '%Y-%m-%d' ),
    	`status` 
    HAVING
    	`status` = 3 
    	AND DATE_FORMAT( cdate, '%Y-%m-%d' )>= '2022-01-02' 
    	AND DATE_FORMAT( cdate, '%Y-%m-%d' )<= '2022-08-16' 
    ORDER BY
    	DATE_FORMAT(cdate,'%Y-%m-%d')
    

    执行结果如下: image

    翻译成go代码如下:

    func (*S3Order) ListBillCount(status int, cdate_begin, cdate_end string) ([]*model.S3OrderBill, int64, error) {
    	fmt.Println("ListBillCount参数:", status, cdate_begin, cdate_end)
    	qryBill, qryBillDo := query.S3OrderBillDo()
    	expr := []gen.Condition{}
    	if status > 0 {
    		expr = append(expr, qryBill.Status.Eq(int32(status)))
    	}
    	cdate := qryBill.Cdate.DateFormat("%Y-%m-%d")
    	if cdate_begin != "" {
    		// expr = append(expr, cdate.Gte(cdate_begin))
    		cbegin := cdate_begin + " 00:00:00"
    		fmt.Println(cbegin)
    		begin, err := time.Parse("2006-01-02 15:04:05", cbegin)
    		if err != nil {
    			fmt.Println(err.Error())
    		} else {
    			expr = append(expr, qryBill.Cdate.Gte(begin))
    		}
    	}
    	if cdate_end != "" {
    		// expr = append(expr, cdate.Lte(cdate_end))
    		cend := cdate_end + " 23:59:59"
    		fmt.Println(cend)
    		end, err := time.Parse("2006-01-02 15:04:05", cend)
    		if err != nil {
    			fmt.Println(err.Error())
    		} else {
    			expr = append(expr, qryBill.Cdate.Lte(end))
    		}
    	}
    	action := qryBillDo.Select(qryBill.ID.Count().As("num"), qryBill.Amount.Sum().As("amount"), qryBill.Status, cdate.As("cdate")).
    		Having(expr...).
    		Group(cdate, qryBill.Status).
    		Order(cdate)
    	outList := []*model.S3OrderBill{}
    	err := action.Scan(&outList)
    	return outList, int64(len(outList)), err
    }
    

    执行出现如下错误:

    Filter --------------------> /admin/s3/order/SearchBill7Day /admin/login true
    ListBillCount参数: 3 2022-08-09 2022-08-16
    
    2022/08/16 21:21:24 /Users/zhushuyan/go/pkg/mod/gorm.io/[email protected]/do.go:799 Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `cdate`,`s3_order_bill`.`status` HAVING `s3_order_bill`.`status` = ? AND DATE' at line 1
    [2.235ms] [rows:-] SELECT COUNT(`s3_order_bill`.`id`) AS `num`,SUM(`s3_order_bill`.`amount`) AS `amount`,`s3_order_bill`.`status`,DATE_FORMAT(`s3_order_bill`.`cdate`,'%Y-%m-%d') AS `cdate` FROM `s3_order_bill` GROUP BY DATE_FORMAT(`s3_order_bill`.`cdate`,3) AS `cdate`,`s3_order_bill`.`status` HAVING `s3_order_bill`.`status` = '%Y-%m-%d' AND DATE_FORMAT(`s3_order_bill`.`cdate`,'2022-08-09') >= '%Y-%m-%d' AND DATE_FORMAT(`s3_order_bill`.`cdate`,'2022-08-16') <= ? ORDER BY DATE_FORMAT(`s3_order_bill`.`cdate`,?) AS `cdate`
    Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `cdate`,`s3_order_bill`.`status` HAVING `s3_order_bill`.`status` = ? AND DATE' at line 1
    

    为了方便查看,将生成的sql格式化如下:

    SELECT
    	COUNT( `s3_order_bill`.`id` ) AS `num`,
    	SUM( `s3_order_bill`.`amount` ) AS `amount`,
    	`s3_order_bill`.`status`,
    	DATE_FORMAT( `s3_order_bill`.`cdate`, '%Y-%m-%d' ) AS `cdate` 
    FROM
    	`s3_order_bill` 
    GROUP BY
    	DATE_FORMAT( `s3_order_bill`.`cdate`, 3 ),
    	`s3_order_bill`.`status` 
    HAVING
    	`s3_order_bill`.`status` = '2022-08-09 00:00:00' 
    	AND `s3_order_bill`.`cdate` >= '2022-08-16 23:59:59' 
    	AND `s3_order_bill`.`cdate` <= ? 
    ORDER BY
    	DATE_FORMAT(
    	`s3_order_bill`.`cdate`,?)
    

    问题一:group by生成错误 问题二:having生成错误 问题三:order by生成错误

    https://github.com/go-gorm/playground/pull/1

    Description

    opened by zsy619 20
  • 查询是否可以生成计算列

    查询是否可以生成计算列

    查询字段或where条件,是否可以多个字段拼接组合

    如以下sql

    SELECT c.code as bcode,c.cdate,c.status,a.*,(a.sto_qty - a.dist_qty - a.allot_qty + a.retn_qty - a.allot_qty - a.loss_qty - a.borrow_qty + a.retn_qty2) as lft_qty,b.spec,b.type,b.unit,b.mate 
    FROM s3_rec_item a
    LEFT JOIN s3_cat_item b ON a.item_id = b.id
    LEFT JOIN s3_rec_bill c ON a.rec_id = c.id
    WHERE c.`status` = 3 
    AND (a.sto_qty - a.dist_qty - a.allot_qty + a.retn_qty - a.allot_qty - a.loss_qty - a.borrow_qty + a.retn_qty2) > 0
    

    问题1:字段

    (a.sto_qty - a.dist_qty - a.allot_qty + a.retn_qty - a.allot_qty - a.loss_qty - a.borrow_qty + a.retn_qty2) as lft_qty
    

    如何写

    问题2:查询条件

    (a.sto_qty - a.dist_qty - a.allot_qty + a.retn_qty - a.allot_qty - a.loss_qty - a.borrow_qty + a.retn_qty2) > 0
    

    如何写

    Motivation

    Related Issues

    opened by zsy619 17
  • How to Generate Models and Curd Queries for Mysql tables with foreign keys.

    How to Generate Models and Curd Queries for Mysql tables with foreign keys.

    Want to generate Models and curd queries for Mysql tables with foreign keys, how to call generate function ?

    Mysql Tables

    CREATE TABLE `customers` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `created_at` datetime(3) DEFAULT NULL,
      `updated_at` datetime(3) DEFAULT NULL,
      `deleted_at` datetime(3) DEFAULT NULL,
      `name` Varchar(20) DEFAULT NULL,
      `cc_id` bigint(20) unsigned DEFAULT NULL,
      PRIMARY KEY (`id`),
      CONSTRAINT `credit_card_ref` FOREIGN KEY (`cc_id`) REFERENCES `credit_cards` (`id`),
      KEY `idx_customers_deleted_at` (`deleted_at`)
    ) ENGINE=InnoDB;
    
    CREATE TABLE `credit_cards` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `created_at` datetime(3) DEFAULT NULL,
      `updated_at` datetime(3) DEFAULT NULL,
      `deleted_at` datetime(3) DEFAULT NULL,
      `number` longtext,
      PRIMARY KEY (`id`),
      KEY `idx_credit_cards_deleted_at` (`deleted_at`)
    ) ENGINE=InnoDB;
    
    

    Gen code

    customer := g.GenerateModel("customers")
    g.GenerateModel("credit_cards")
    //g.ApplyBasic(card, customer)
    g.Execute()
    

    and also tried calling it as below

    card := g.GenerateModel("credit_cards")
    g.GenerateModel("customers", gen.FieldRelate(field.HasOne, "credit_cards", card,
    	&field.RelateConfig{
    		// RelateSlice: true,
    		GORMTag: "foreignKey:credit_card_ref",
    	}))
    //g.ApplyBasic(card, customer)
    g.Execute()
    

    but it returns Models as

    type Customer struct {
    	ID           int64          `gorm:"column:id;type:bigint(20) unsigned;primaryKey;autoIncrement:true" json:"id"`
    	CreatedAt    *time.Time     `gorm:"column:created_at;type:datetime(3)" json:"created_at"`
    	UpdatedAt    *time.Time     `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`
    	DeletedAt    gorm.DeletedAt `gorm:"column:deleted_at;type:datetime(3);index:idx_customers_deleted_at,priority:1" json:"deleted_at"`
    	Name         *string        `gorm:"column:name;type:varchar(20)" json:"name"`
    	CcID         *int64         `gorm:"column:cc_id;type:bigint(20) unsigned;index:credit_card_ref,priority:1" json:"cc_id"`
    	credit_cards CreditCard     `gorm:"foreignKey:credit_card_ref" json:"credit_cards"`
    }
    
    type CreditCard struct {
    	ID        int64          `gorm:"column:id;type:bigint(20) unsigned;primaryKey;autoIncrement:true" json:"id"`
    	CreatedAt *time.Time     `gorm:"column:created_at;type:datetime(3)" json:"created_at"`
    	UpdatedAt *time.Time     `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`
    	DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:datetime(3);index:idx_credit_cards_deleted_at,priority:1" json:"deleted_at"`
    	Number    *string        `gorm:"column:number;type:longtext" json:"number"`
    }
    

    version used v0.2.28

    opened by avvineed 16
  • 能否支持下字段属性的枚举生成

    能否支持下字段属性的枚举生成

    在编码过程中,经常会遇到用某个数值来表示某种状态、类型或者阶段的情况,比如有这样一个枚举:

    public enum ComputerState {
        OPEN(10),         //开启
        CLOSE(11),         //关闭
        OFF_LINE(12),     //离线
        FAULT(200),     //故障
        UNKNOWN(255);     //未知
    
        private int code;
        ComputerState(int code) { this.code = code; }
    }
    
    

    通常我们希望将表示状态的数值存入数据库,即ComputerState.OPEN存入数据库取值为10。

    能否通过field comment的中备注,来生成对应枚举值

    比如可以约定注释检查规则的正则表达式如下

    REMARKS_PATTERN = ".*\\s*\\[\\s*(\\w+\\s*\\(\\s*[\\u4e00-\\u9fa5_\\-a-zA-Z0-9]+\\s*\\)\\s*:\\s*[\\u4e00-\\u9fa5_\\-a-zA-Z0-9]+\\s*\\,?\\s*)+\\s*\\]\\s*.*";
    
    
    
    CREATE TABLE `tb` (
      `type` smallint(3) COMMENT '注释[success(0):成功, fail(1):失败]',                       
    );
    

    提取出字段属性相应的枚举

    type Type int
    
    const (
            Success  Type = 0 //成功
            Fail Type = 1 //失败
    )
    
    
    
    opened by waltcow 16
  • 如何在事务中删除关联的行

    如何在事务中删除关联的行

    Your Question

    比如现在我有这么两个表:

    type User struct {
        ID                   int	
        UserInfo             UserInfo
        CreatedAt            time.Time
        UpdatedAt            time.Time
    }
    
    type UserInfo struct {
        ID           int
        UserID       int
        DisplayName  string
        Address      string
        Age          int
        CreatedAt    time.Time
        UpdatedAt    time.Time
    }
    
    

    我需要在事务中删除User及其关联的UserInfo,代码需要怎么写呢? 下面👇这个代码只会删除掉User,但UserInfo没有删除

    q := query.Use(db)
    
    q.Transaction(func(tx *query.Query) error {
      if _, err := tx.User.WithContext(ctx).Where(tx.User.ID.Eq(100)).Delete(); err != nil {
        return err
      }
      return nil
    })
    

    另外,如果在删除的时候,需要根据 join 后的过滤条件进行删除(这里我需要删除的是 user),那么,根据下面的代码但生成的 sql 会报错,正确的做法是什么?

    q := query.Use(db)
    
    // 这里生成的 sql 有误,大概长这样:
    // DELETE FROM `users` INNER JOIN `user_infos` ON `user_infos`.`user_id` = `users`.`id` WHERE `user_infos`.`id` = 100 
    q.Transaction(func(tx *query.Query) error {
    	if _, err := tx.User.WithContext(ctx).
    		Join(tx.UserInfo, tx.UserInfo.UserID.EqCol(tx.User.ID)).
    		Where(tx.UserInfo.ID.Eq(100)).
    		Delete(); err != nil {
    		return err
    	}
    	return nil
    })
    
    

    The document you expected this should be explained

    Expected answer

    opened by leeming87v5 14
  • FindOne API

    FindOne API

    Describe the feature

    FindOne => db.Limit(1).Find(&user)

    https://gorm.io/docs/query.html

    If you want to avoid the ErrRecordNotFound error, you could use Find like db.Limit(1).Find(&user), the Find method accepts both struct and slice data

    Motivation

    Related Issues

    opened by to2false 13
  • 使用问题求教~

    使用问题求教~

    Your Question

    1. 比较好奇为什么 ResultInfo 中会有个 error, 比如像 Updates 方法本身就返回了一个 error 了,为什么又将 error 放到 ResultInfo 中呢?
    2. gen 中的 Select 不可以和 struct 一起使用吗?下列代码为什么不能更新 Select 的字段?
    	schedule := query.Use(preload.DB).Schedule
    	_, err := schedule.WithContext(ctx).
    		Select(schedule.Title, schedule.Content, schedule.BeginTime, schedule.EndTime, schedule.UpdatedAt).
    		Where(schedule.ID.Eq(input.ID), schedule.DeletedAt.Eq(0)).
    		Updates(newValue)
    

    对应控制台的输出为:

    UPDATE `tblSchedule` SET `updated_at`=1658389286 WHERE `tblSchedule`.`id` = 1 AND `tblSchedule`.`deleted_at` = 0
    

    麻烦大佬看下~

    Expected answer

    opened by gh-zhangpeng 10
  • 期望增加配置分片参数、支持分表模型

    期望增加配置分片参数、支持分表模型

    水平分表创建模型需要建立多张表,期望收敛在一个模型中,能定制模型的TableName

    ###DDL

    CREATE TABLE IF NOT EXISTS `mytables_[0-127]` (
    	`ID` int(11) NOT NULL," 
    	`username` varchar(16) DEFAULT NULL,
    	`age` int(8) NOT NULL," 
    	`phone` varchar(11) NOT NULL,
    	INDEX `idx_username` (`username`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    

    生成模型

    g.GenerateModelAs("mytables_0", "Mytable")
    

    model

    package model
    
    const TableNameMytable = "mytables_0"
    
    // Mytable mapped from table <mytables_[0-127]>
    type Mytable struct {
    	ID       int32   `gorm:"column:ID;type:int(11);not null" json:"ID_example"`
    	Username *string `gorm:"column:username;type:varchar(16);index:idx_username,priority:1;default:NULL" json:"username_example"`
    	Age      int32   `gorm:"column:age;type:int(8);not null" json:"age_example"`
    	Phone    string  `gorm:"column:phone;type:varchar(11);not null" json:"phone_example"`
    }
    
    // TableName Mytable's table name
    func (*Mytable) TableName() string {
    	return TableNameMytable
    }
    
    

    期望在模板中增加一个分片参数、通过分片参数可以自定义TableName()方法。

    image

    image

    预期想要生成的模型

    package model
    
    import (
    	"fmt"
    )
    
    const TableNameMytable = "mytables"
    const TableNameMytableShardNumber = 128
    
    // Mytable mapped from table <mytables_[0-127]>
    type Mytable struct {
    	ID       int32   `gorm:"column:ID;type:int(11);not null" json:"ID_example"`
    	Username *string `gorm:"column:username;type:varchar(16);index:idx_username,priority:1;default:NULL" json:"username_example"`
    	Age      int32   `gorm:"column:age;type:int(8);not null" json:"age_example"`
    	Phone    string  `gorm:"column:phone;type:varchar(11);not null" json:"phone_example"`
    }
    
    // TableName Mytable's table name
    func (*Mytable) TableName(id int32) string {
    	return TableNameMytable + fmt.Sprintf("_%v", id%TableNameMytableShardNumber) // 自定义方法
    
    opened by wulorn 10
  • Mock with interface style

    Mock with interface style

    Describe the feature

    Interface style

    Motivation

    Why this project doesn't write in interface style ?

    Related Issues

    It's impossible to mock xxxDo struct when importing dao in other packages, the only way to write unit test for these packages is to launch a sqlite database then fill some fake records. Is there any way to mock method of xxxDo struct? if not, I think it's not appropriate for serious project, only suitable for project that is not in need for unit test.

    opened by zhangzitao 10
  • Config Struct OutFile field describe error

    Config Struct OutFile field describe error

    Description

    OutFile      string // query code file name, default: gen.go
    

    OutFile field is describe use for query code file name.

    but the real behavior is query code file generate PATH and the file name always gen.go

    // config.go#122L
    if cfg.OutFile == "" {
    	cfg.OutFile = cfg.OutPath + "/gen.go"
    }
    
    // generator.go#321L
    err = g.output(g.OutFile, buf.Bytes())
    if err != nil {
    	return err
    }
    g.successInfo("generate query file: " + g.OutFile)
    

    this comment mislead a lot...

    opened by aizk 9
  • Return interface instead of private struct for query objects

    Return interface instead of private struct for query objects

    When I write

    dto := query.Use(db).MyDataTransferObject
    

    I hope that the type of dto is exported so that I can use it as a function input/output.

    Motivation

    I need to process dto in another function to improve code reusability.

    Related Issues

    None.

    opened by lichuan0620 9
  • 推荐实现自定义类型 tag的实现

    推荐实现自定义类型 tag的实现

    IP       netip.Addr      `json:"ip" gorm:"serializer:auto;comment:auto|netip.Addr|注册IP"`
    

    抛砖引玉 先手动写struct 用comment来配置当前的类型与serializer 名称(对于自定义类型在自定义serializer里面实现就好了)

    		arr := strings.Split(comment, "|")
    		comment = arr[1]
    		if len(arr) == 3 {
    			fieldType = arr[1]
    		}
    	}
    --------------------
    	if d, ok := c.Comment(); ok {
    		if strings.Contains(d, "|") {
    			arr := strings.Split(d, "|")
    			if len(arr) > 2 && arr[0] != "" {
    				buf.WriteString(";serializer:" + arr[0])
    			}
    		}
    	}
    

    这样子就不需要在手动写类型了, 就是写struct 稍微慢点

    opened by hinego 5
  • Find method can return slice of structs or pointers

    Find method can return slice of structs or pointers

    Describe the feature

    Some libraries accept slice of structs and some use slice of pointers, but find method can only generate slice of pointers.

    hopefully the return value can be changed at configuration or execution stage.

    Motivation

    Related Issues

    opened by ddman 0
  • 生成的boxBelongs不完整

    生成的boxBelongs不完整

    Description

    Model

    type Base struct {
    	ID        uint           `gorm:"primarykey" json:"id"`
    	CreatedAt time.Time      `json:"created_at"`
    	UpdatedAt time.Time      `json:"updated_at"`
    	DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
    }
    
    type Area struct {
    	Base
    	Shelves []*Shelf `json:"shelves,omitempty"`
    }
    
    type Shelf struct {
    	Base
    	AreaID uint  `gorm:"index" json:"area_id" `
    	Area   *Area `gorm:"foreignkey:AreaID" json:"area,omitempty"`
    	Boxes []*Box `json:"boxes,omitempty"`
    }
    
    type Box struct {
    	Base
    	ShelfID uint `json:"shelf_id"`
    	Archives []*Archive `json:"archives,omitempty"`
    }
    
    type Archive struct {
    	Base
    	BoxID uint `gorm:"index" json:"box_id"`
    	Box *Box `json:"box,omitempty"`
    }
    

    描述

    使用的 gen 版本为当前最新

    当我用这些模型结构定义生成代码后, 我发现 BoxboxBelongsToShelf 会缺失上一层的关系

    type box struct {
    	boxDo boxDo
    
    	ALL       field.Asterisk
    	ID        field.Uint
    	CreatedAt field.Time
    	UpdatedAt field.Time
    	DeletedAt field.Field
    	ShelfID   field.Uint
    	Archives  boxHasManyArchives
    
    	Shelf boxBelongsToShelf
    
    	fieldMap map[string]field.Expr
    }
    
    ...
    
    type boxBelongsToShelf struct {
    	db *gorm.DB
    
    	field.RelationField
    }
    

    但此时, ArchiveBelongsTo 属性则正常

    type archive struct {
    	archiveDo archiveDo
    
    	ALL       field.Asterisk
    	ID        field.Uint
    	CreatedAt field.Time
    	UpdatedAt field.Time
    	DeletedAt field.Field
    	BoxID     field.Uint
    	Box       archiveBelongsToBox
    
    	fieldMap map[string]field.Expr
    }
    
    ...
    
    type archiveBelongsToBox struct {
    	db *gorm.DB
    
    	field.RelationField
    
    	Shelf struct {
    		field.RelationField
    		Area struct {
    			field.RelationField
    			Shelves struct {
    				field.RelationField
    			}
    		}
    		Boxes struct {
    			field.RelationField
    		}
    	}
    	Archives struct {
    		field.RelationField
    		Box struct {
    			field.RelationField
    		}
    	}
    }
    

    如果我将 ArchiveBox 属性去掉的话...生成的 boxBelongsToShelf 结构将会是正常的

    
    type box struct {
    	boxDo boxDo
    
    	ALL       field.Asterisk
    	ID        field.Uint
    	CreatedAt field.Time
    	UpdatedAt field.Time
    	DeletedAt field.Field
    	ShelfID   field.Uint
    	Archives  boxHasManyArchives
    
    	Shelf boxBelongsToShelf
    
    	fieldMap map[string]field.Expr
    }
    
    
    type boxBelongsToShelf struct {
    	db *gorm.DB
    
    	field.RelationField
    
    	Area struct {
    		field.RelationField
    		Shelves struct {
    			field.RelationField
    		}
    	}
    	Boxes struct {
    		field.RelationField
    		Shelf struct {
    			field.RelationField
    		}
    		Archives struct {
    			field.RelationField
    		}
    	}
    }
    

    现在我是在修改前后生成代码, 再合并一下缺失的部分进行处理的, 并没有发现什么问题, 预加载正常使用.

    希望能帮忙看看这个缺失的结构!

    opened by icepie 0
  • fix: type tag closed

    fix: type tag closed

    • [x] Do only one thing
    • [x] Non breaking API changes
    • [x] Tested

    What did this pull request do?

    • 删除生成model的所有type tag

    User Case Description

    • 通过postgresql源生成的model,即使FieldWithTypeTag关闭,也会生成type tag
    • 带上type tag的model,在使用sqlite driver的时候,数据类型不兼容
    • 详情请看描述:https://github.com/go-gorm/gen/issues/638
    opened by kooksee 0
  • 从postgresql导出的model,无法在sqlite里面使用

    从postgresql导出的model,无法在sqlite里面使用

    GORM Playground Link

    https://github.com/go-gorm/playground/pull/1

    Description

    1. 版本:gen=v0.3.16,gorm=v1.23.9-0.20220713102635-3262daf8d468
    2. gen model开启WithUnitTest,数据源为postgresql
    3. model
     type User struct {
    	ID              int32         `gorm:"column:id;type:integer;primaryKey;autoIncrement:true" json:"id"`
    	Password        string        `gorm:"column:password;type:character varying(128);not null" json:"password"`
    	LastLogin       time.Time     `gorm:"column:last_login;type:timestamp with time zone" json:"last_login"`
    	IsSuperuser     bool          `gorm:"column:is_superuser;type:boolean;not null" json:"is_superuser"`
    	Username        string        `gorm:"column:username;type:character varying(254);not null" json:"username"`
    	FirstName       string        `gorm:"column:first_name;type:character varying(30);not null" json:"first_name"`
    	LastName        string        `gorm:"column:last_name;type:character varying(30);not null" json:"last_name"`
    	Email           string        `gorm:"column:email;type:character varying(254);not null" json:"email"`
    	IsStaff         bool          `gorm:"column:is_staff;type:boolean;not null" json:"is_staff"`
    	IsActive        bool          `gorm:"column:is_active;type:boolean;not null" json:"is_active"`
    	UpdatedAt       time.Time     `gorm:"column:updated_at;type:timestamp with time zone;not null" json:"updated_at"`
    }
    
    // TableName User's table name
    func (*User) TableName() string {
    	return TableNameUser
    }
    
    1. query 里面的单元测试通不过,错误信息 Scan error on column index 1, name "created_at": unsupported Scan, storing driver.Value type string into type *time.Time
    2. 排查原因:单元测试用的sqlite,time.Time的type tag,sqlite和postgresql不兼容,所以解析失败
    opened by kooksee 0
  • 自定义的 model  生成私有 结构体,是否可以生成注释?

    自定义的 model 生成私有 结构体,是否可以生成注释?

    Your Question

    #621 似乎可以自动生成私有模型注释,但是根据已有 model 生成代码,不会生成注释

    The document you expected this should be explained

    Expected answer

    希望自定义的 model 也可以生成注释

    opened by shuqingzai 0
Releases(v0.3.16)
  • v0.3.16(Aug 31, 2022)

    What's Changed

    • fix:data race(#588) by @riverchu in https://github.com/go-gorm/gen/pull/625
    • tests: unit test for generate by @riverchu in https://github.com/go-gorm/gen/pull/626
    • feat: generate column comment in query struct by @riverchu in https://github.com/go-gorm/gen/pull/621
    • revert: "fix: ParseStructRelationShip with cache" (#616) by @qqxhb in https://github.com/go-gorm/gen/pull/631

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.15...v0.3.16

    Source code(tar.gz)
    Source code(zip)
  • v0.3.15(Aug 26, 2022)

    What's Changed

    • feat: allow default tag CURRENT_TIMESTAMP by @riverchu in https://github.com/go-gorm/gen/pull/596
    • tests: add field unit test by @riverchu in https://github.com/go-gorm/gen/pull/598
    • feat: ignore empty table by @qqxhb in https://github.com/go-gorm/gen/pull/601
    • fix: compatible with add method opt in main by @to2false in https://github.com/go-gorm/gen/pull/586
    • feat: update subquery with alias by @riverchu in https://github.com/go-gorm/gen/pull/606
    • feat: add new field type Asterisk by @riverchu in https://github.com/go-gorm/gen/pull/609
    • feat: support custom field type by @qqxhb in https://github.com/go-gorm/gen/pull/615
    • fix: ParseStructRelationShip with cache by @kiancchen in https://github.com/go-gorm/gen/pull/616

    New Contributors

    • @to2false made their first contribution in https://github.com/go-gorm/gen/pull/586
    • @kiancchen made their first contribution in https://github.com/go-gorm/gen/pull/616
    • @SliverHorn made their first contribution in https://github.com/go-gorm/gen/pull/613

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.14...v0.3.15

    Source code(tar.gz)
    Source code(zip)
  • v0.3.14(Aug 1, 2022)

    What's Changed

    • fix: gen interface tmpl by @qqxhb in https://github.com/go-gorm/gen/pull/570
    • feat: add method opt by @qqxhb in https://github.com/go-gorm/gen/pull/572
    • feat(field): column stream operate by @riverchu in https://github.com/go-gorm/gen/pull/579

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.13...v0.3.14

    Source code(tar.gz)
    Source code(zip)
  • v0.3.13(Jul 20, 2022)

    What's Changed

    • fix(do): refactor select buildExpr for association by @riverchu in https://github.com/go-gorm/gen/pull/542
    • feat: optimize AssociationFields for the association by @riverchu in https://github.com/go-gorm/gen/pull/543
    • feat: adjust generated data type by @wulorn in https://github.com/go-gorm/gen/pull/531
    • feat(do): check detail for clause Insert by @riverchu in https://github.com/go-gorm/gen/pull/547
    • fix: gen pointer field by @qqxhb in https://github.com/go-gorm/gen/pull/549
    • fix: set RelationshipType from schema by @tongyuantongyu in https://github.com/go-gorm/gen/pull/556
    • feat(do): delete receive models by @riverchu in https://github.com/go-gorm/gen/pull/546
    • feat: implement add/sub col expression by @riverchu in https://github.com/go-gorm/gen/pull/564
    • fix: Results are not returned on "Returning" by @riverchu in https://github.com/go-gorm/gen/pull/565

    New Contributors

    • @wulorn made their first contribution in https://github.com/go-gorm/gen/pull/531
    • @tongyuantongyu made their first contribution in https://github.com/go-gorm/gen/pull/556
    • @lluckyboi made their first contribution in https://github.com/go-gorm/gen/pull/550

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.12...v0.3.13

    Source code(tar.gz)
    Source code(zip)
  • v0.3.12(Jul 13, 2022)

    What's Changed

    • fix(generate): log out of range by @idersec in https://github.com/go-gorm/gen/pull/538
    • fix(generate): log end Line out of range by @riverchu in https://github.com/go-gorm/gen/pull/539
    • fix(generate): import pkg path uniq by @riverchu in https://github.com/go-gorm/gen/pull/540

    New Contributors

    • @StellarisW made their first contribution in https://github.com/go-gorm/gen/pull/530

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.11...v0.3.12

    Source code(tar.gz)
    Source code(zip)
  • v0.3.11(Jul 8, 2022)

    What's Changed

    • fix: template typo #523 by @riverchu in https://github.com/go-gorm/gen/pull/524
    • chore(deps): remove replace by @riverchu in https://github.com/go-gorm/gen/pull/527

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.10...v0.3.11

    Source code(tar.gz)
    Source code(zip)
  • v0.3.10(Jul 6, 2022)

    What's Changed

    • feat: add Clauses method to Dao by @riverchu in https://github.com/go-gorm/gen/pull/508
    • fix: generate unit test for custom method with non basic type by @XiaYinchang in https://github.com/go-gorm/gen/pull/509
    • fix: many2many relationship typo by @riverchu in https://github.com/go-gorm/gen/pull/520

    New Contributors

    • @XiaYinchang made their first contribution in https://github.com/go-gorm/gen/pull/509

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.9...v0.3.10

    Source code(tar.gz)
    Source code(zip)
  • v0.3.9(Jul 1, 2022)

    What's Changed

    • feat: update template for WriteDB and ReadDB by @qqxhb in https://github.com/go-gorm/gen/pull/475

    • feat: support base struct bind custom method (#352) by @riverchu in https://github.com/go-gorm/gen/pull/464

    • feat: gen index by @qqxhb in https://github.com/go-gorm/gen/pull/484

    • feat: add gen.FieldComment to rewrite struct comment by @Trim21 in https://github.com/go-gorm/gen/pull/486

    • feat: add imports from DIY interface package to accelerate imports.Process by @unnamed42 in https://github.com/go-gorm/gen/pull/488

    • feat: generate with interface by @riverchu in https://github.com/go-gorm/gen/pull/492

    • feat: accept file name without path by @riverchu in https://github.com/go-gorm/gen/pull/495

    • feat: refactor package check by @riverchu in https://github.com/go-gorm/gen/pull/504

    • feat: preload unscoped by @riverchu in https://github.com/go-gorm/gen/pull/505

    • fix: typo by @riverchu in https://github.com/go-gorm/gen/pull/474

    • fix: rename template variable name to avoid naming conflicts with package name by @xsxnet in https://github.com/go-gorm/gen/pull/487

    • fix: template field name by @riverchu in https://github.com/go-gorm/gen/pull/498

    • fix: generate []byte field with query type field.Bytes by @riverchu in https://github.com/go-gorm/gen/pull/499

    • fix:fix bytes->byte,and rename function name by @idersec in https://github.com/go-gorm/gen/pull/500

    New Contributors

    • @Trim21 made their first contribution in https://github.com/go-gorm/gen/pull/486
    • @xsxnet made their first contribution in https://github.com/go-gorm/gen/pull/487
    • @unnamed42 made their first contribution in https://github.com/go-gorm/gen/pull/488

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.8...v0.3.9

    Source code(tar.gz)
    Source code(zip)
  • v0.3.8(Jun 13, 2022)

    What's Changed

    • feat: ignore empty string by @riverchu in https://github.com/go-gorm/gen/pull/473

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.7...v0.3.8

    Source code(tar.gz)
    Source code(zip)
  • v0.3.7(Jun 13, 2022)

    What's Changed

    • fix: remove verbose quote for default tag by @riverchu in https://github.com/go-gorm/gen/pull/457
    • fix: accept clause dbresolver.Operation by @riverchu in https://github.com/go-gorm/gen/pull/466
    • feat: support JSONOverlapsExpression by @radioinmyhead in https://github.com/go-gorm/gen/pull/467
    • feat: add base method ReadDB and WriteDB by @qqxhb in https://github.com/go-gorm/gen/pull/468
    • feat: accept DIY new struct name (#456) by @riverchu in https://github.com/go-gorm/gen/pull/458

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.6...v0.3.7

    Source code(tar.gz)
    Source code(zip)
  • v0.3.6(Jun 2, 2022)

  • v0.3.5(Jun 2, 2022)

    What's Changed

    • fix: sqlite data type by @qqxhb in https://github.com/go-gorm/gen/pull/434
    • style: optimize code style by @riverchu in https://github.com/go-gorm/gen/pull/443
    • style: fix typo by @michaelzx in https://github.com/go-gorm/gen/pull/450
    • fix: ignore zero value default tag by @riverchu in https://github.com/go-gorm/gen/pull/451
    • feat: support FromUnixTime by @riverchu in https://github.com/go-gorm/gen/pull/452

    New Contributors

    • @yikakia made their first contribution in https://github.com/go-gorm/gen/pull/435
    • @BigeYoung made their first contribution in https://github.com/go-gorm/gen/pull/447
    • @michaelzx made their first contribution in https://github.com/go-gorm/gen/pull/450

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.4...v0.3.5

    Source code(tar.gz)
    Source code(zip)
  • v0.3.4(Apr 24, 2022)

    What's Changed

    • refactor: generate GORM default tag by @riverchu in https://github.com/go-gorm/gen/pull/433

    New Contributors

    • @web-xiaxia made their first contribution in https://github.com/go-gorm/gen/pull/431

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.3...v0.3.4

    Source code(tar.gz)
    Source code(zip)
  • v0.3.3(Apr 21, 2022)

    What's Changed

    • fix: int default tag without quote by @riverchu in https://github.com/go-gorm/gen/pull/429

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.2...v0.3.3

    Source code(tar.gz)
    Source code(zip)
  • v0.3.2(Apr 21, 2022)

    What's Changed

    • feat: add field's column name by @riverchu in https://github.com/go-gorm/gen/pull/425
    • feat: generate unsigned integer type by @riverchu in https://github.com/go-gorm/gen/pull/426
    • feature: model Joins & Preload methods support multiple RelationField by @alfarih31 in https://github.com/go-gorm/gen/pull/424
    • fix: remove zero value default tag by @riverchu in https://github.com/go-gorm/gen/pull/428

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.1...v0.3.2

    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Apr 18, 2022)

    What's Changed

    • style: remove tag's verbose space by @riverchu in https://github.com/go-gorm/gen/pull/421

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.3.0...v0.3.1

    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Apr 18, 2022)

    What's Changed

    • feature: generate from object by @riverchu in https://github.com/go-gorm/gen/pull/407
    • feat: FindByPage return all result when limit<=0 by @riverchu in https://github.com/go-gorm/gen/pull/410
    • feat(generate): add real/numeric type mapping for sqlite by @riverchu in https://github.com/go-gorm/gen/pull/417

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.44...v0.3.0

    Source code(tar.gz)
    Source code(zip)
  • v0.2.44(Apr 6, 2022)

    What's Changed

    • fix: update table name in schema by @riverchu in https://github.com/go-gorm/gen/pull/393
    • feat(Joins): implement Joins "ON" condition for equal-like clauses & "ORDER BY" relation table columns by @alfarih31 in https://github.com/go-gorm/gen/pull/390
    • feat: implement function REPLACE/CONCAT by @riverchu in https://github.com/go-gorm/gen/pull/400
    • fix: wrap blank default value tag by @riverchu in https://github.com/go-gorm/gen/pull/408
    • feat: support join with sub query by @qqxhb in https://github.com/go-gorm/gen/pull/402

    New Contributors

    • @zhouyusd made their first contribution in https://github.com/go-gorm/gen/pull/391
    • @alfarih31 made their first contribution in https://github.com/go-gorm/gen/pull/390

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.43...v0.2.44

    Source code(tar.gz)
    Source code(zip)
  • v0.2.43(Mar 8, 2022)

    What's Changed

    • fix: count without offset in FindByPage by @riverchu in https://github.com/go-gorm/gen/pull/387

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.42...v0.2.43

    Source code(tar.gz)
    Source code(zip)
  • v0.2.42(Mar 3, 2022)

    What's Changed

    • fix: generator GenerateAllTable unuse opts by @MOHENOO in https://github.com/go-gorm/gen/pull/381
    • feat: implement returning by @riverchu in https://github.com/go-gorm/gen/pull/383

    New Contributors

    • @MOHENOO made their first contribution in https://github.com/go-gorm/gen/pull/381

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.41...v0.2.42

    Source code(tar.gz)
    Source code(zip)
  • v0.2.41(Feb 25, 2022)

    What's Changed

    • feat: return count when limit == 0 by @riverchu in https://github.com/go-gorm/gen/pull/378
    • fix: other driver by @qqxhb in https://github.com/go-gorm/gen/pull/379

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.40...v0.2.41

    Source code(tar.gz)
    Source code(zip)
  • v0.2.40(Feb 24, 2022)

    What's Changed

    • feat: support mult driver by @qqxhb in https://github.com/go-gorm/gen/pull/375
    • perf: optimize FindByPage by @riverchu in https://github.com/go-gorm/gen/pull/377

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.39...v0.2.40

    Source code(tar.gz)
    Source code(zip)
  • v0.2.39(Feb 7, 2022)

    What's Changed

    • feat(field): method accept driver.Valuer by @riverchu in https://github.com/go-gorm/gen/pull/362
    • feat(generate): add Table method by @riverchu in https://github.com/go-gorm/gen/pull/365
    • feat(do): implement WithResult method by @riverchu in https://github.com/go-gorm/gen/pull/366
    • feat(field): export FieldOpt by @riverchu in https://github.com/go-gorm/gen/pull/371
    • feat: add field coverable option by @riverchu in https://github.com/go-gorm/gen/pull/372

    New Contributors

    • @sudopower made their first contribution in https://github.com/go-gorm/gen/pull/363

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.38...v0.2.39

    Source code(tar.gz)
    Source code(zip)
  • v0.2.38(Jan 22, 2022)

    What's Changed

    • fix(table): generate field with default value to pointer by @riverchu in https://github.com/go-gorm/gen/pull/361

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.37...v0.2.38

    Source code(tar.gz)
    Source code(zip)
  • v0.2.37(Jan 18, 2022)

    What's Changed

    • feat(generate): accept []interface{} by @riverchu in https://github.com/go-gorm/gen/pull/358
    • fix(generate): created/updated_at without default by @riverchu in https://github.com/go-gorm/gen/pull/359

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.36...v0.2.37

    Source code(tar.gz)
    Source code(zip)
  • v0.2.36(Jan 18, 2022)

    What's Changed

    • feat: add EXISTS and NOT EXISTS support by @myml in https://github.com/go-gorm/gen/pull/349
    • fix: fix updates model copy by @riverchu in https://github.com/go-gorm/gen/pull/356

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.35...v0.2.36

    Source code(tar.gz)
    Source code(zip)
  • v0.2.35(Jan 11, 2022)

    What's Changed

    • fix(do): group by expression by @riverchu in https://github.com/go-gorm/gen/pull/347
    • chore(deps): bump gorm.io/driver/mysql from 1.2.2 to 1.2.3 by @dependabot in https://github.com/go-gorm/gen/pull/343

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.34...v0.2.35

    Source code(tar.gz)
    Source code(zip)
  • v0.2.34(Jan 7, 2022)

    What's Changed

    • chore(deps): remove replace by @riverchu in https://github.com/go-gorm/gen/pull/340

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.33...v0.2.34

    Source code(tar.gz)
    Source code(zip)
  • v0.2.33(Jan 7, 2022)

    What's Changed

    • feat(generate): without empty query dir by @riverchu in https://github.com/go-gorm/gen/pull/335
    • feat(gentool): generate only model by @riverchu in https://github.com/go-gorm/gen/pull/336
    • chore(deps): replace golang.org/x/net by @riverchu in https://github.com/go-gorm/gen/pull/329

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.32...v0.2.33

    Source code(tar.gz)
    Source code(zip)
  • v0.2.32(Dec 30, 2021)

    What's Changed

    • style(generate): remove verbose log by @riverchu in https://github.com/go-gorm/gen/pull/328

    Full Changelog: https://github.com/go-gorm/gen/compare/v0.2.31...v0.2.32

    Source code(tar.gz)
    Source code(zip)
Owner
null
100% type-safe ORM for Go (Golang) with code generation and MySQL, PostgreSQL, Sqlite3, SQL Server support. GORM under the hood.

go-queryset 100% type-safe ORM for Go (Golang) with code generation and MySQL, PostgreSQL, Sqlite3, SQL Server support. GORM under the hood. Contents

Denis Isaev 679 Sep 27, 2022
opentracing integration with GORM

gorm-opentracing opentracing support for gorm2. Features Record SQL in span logs. Record Result in span logs. Record Table in span tags. Record Error

null 75 Sep 21, 2022
Converts a database into gorm structs and RESTful api

gen The gen tool produces a CRUD (Create, read, update and delete) REST api project template from a given database. The gen tool will connect to the d

smallnest 1.3k Sep 20, 2022
Scope function for GORM queries provides easy filtering with query parameters

Gin GORM filter Scope function for GORM queries provides easy filtering with query parameters Usage go get github.com/ActiveChooN/gin-gorm-filter Mod

Dmitry Kalinin 7 Aug 29, 2022
A plugin to allow telemetry by NewRelic Go Agent for GORM

GORM NewRelic Telemetry Plugin A plugin to allow telemetry by NewRelic Go Agent for GORM Overview Plugin implementation to add datastore segments on a

Rafael Holanda de Lima 12 Aug 19, 2022
Gorm firebird driver

gorm-firebird GORM firebird driver import: "github.com/flylink888/gorm-firebird" Example: var products []Product dsn := "SYSDBA:[email protected]/sy

null 7 Sep 6, 2022
OpenTelemetry plugin for GORM v2

gorm-opentelemetry OpenTelemetry plugin for GORM v2 Traces all queries along with the query SQL. Usage Example: // Copyright The OpenTelemetry Authors

ZopSmart 0 Jan 11, 2022
CURD using go fiber - gorm - mysql

GO Fiber - CRUD - GORM - Mysql Folder Structure - database | database config |- migration | migration config - middleware | mid

Muhammad Hizbullah 7 Sep 7, 2022
A example of a join table using liquibase and gorm

A example of a join table using liquibase and gorm. Additionally the join table's composite key is used as a composite foreign key for another table.

null 1 Feb 4, 2022
Fiber Clean Architecture With GORM

Fiber Clean Architecture With GORM I offer this repository as a proposal for a c

Vinnicyus Gracindo 17 Sep 11, 2022
Ormtool - 将数据库表转换为golang的结构体,自定义生成tag,如json,gorm,xorm和简单的db信息

数据库表转换为golang 结构体 1. 获取方式 2. 配置说明 # 保存路径 SavePath: "./models/test.go", # 是

Guolei 1 May 30, 2022
Simple-crm-system - Simple CRM system CRUD backend using Go, Fiber, SQLite, Gorm

Simple CRM system CRUD backend using GO, Fiber, Gorm, SQLite Developent go mod t

Oleg Luganskiy 3 Apr 21, 2022
Api-project - Api project with Golang, Gorm, Gorilla-Mux, Postgresql

TECHNOLOGIES GOLANG 1.14 GORM GORILLA-MUX POSTGRESQL API's PATHS For Product Ser

Mustafa Enes Tepe 4 Jul 28, 2022
This library is a complementary library for Gorm (v2) which resolves the first available pool passed to it.

This library is a complementary library for Gorm (v2) which resolves the first available pool passed to it.

Reza Pourmeshki 1 Feb 2, 2022
EZCoin is a control panel for Bitfinex funding, backend is build by Golang, Gin and GORM, frontend is build by angular

EZCoin server is backend for Bitfinex funding, it build by Golang, Gin and GORM.

Dean Lin 0 Feb 7, 2022
RestAPI Starter Template Using Go (Gin + Gorm)

go-gin-gorm-restapi-template Go (Gin + Gorm) を使用した RestAPI 開発のスターターテンプレート RestAPI Starter Template Using Golang (Gin + Gorm) 主要な依存ライブラリ Gin (Web フレームワ

Yuma Ishida 2 Apr 3, 2022
A simple CRUD API made with Go, Postgres, FIber, Gorm and Docker.

golang-test-api A simple CRUD API made with Go, Postgres, FIber, Gorm and Docker. Cloning the repository To clone the repository run the following com

Wesley Dias 9 Aug 14, 2022
A better ORM for Go, based on non-empty interfaces and code generation.

reform A better ORM for Go and database/sql. It uses non-empty interfaces, code generation (go generate), and initialization-time reflection as oppose

null 1.3k Sep 25, 2022
A better ORM for Go, based on non-empty interfaces and code generation.

A better ORM for Go and database/sql. It uses non-empty interfaces, code generation (go generate), and initialization-time reflection as opposed to interface{}, type system sidestepping, and runtime reflection. It will be kept simple.

null 1.3k Sep 21, 2022