Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
jinzhu committed Aug 24, 2020
1 parent 85f0269 commit b28fc19
Show file tree
Hide file tree
Showing 41 changed files with 316 additions and 229 deletions.
3 changes: 2 additions & 1 deletion pages/datatypes.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</head>

<body>
<a href="https://gorm.io">https://gorm.io</a>
<a href="https://gorm.io">https://gorm.io</a><br>
<a href="https://github.com/go-gorm/datatypes" target="_blank">https://github.com/go-gorm/datatypes</a>
</body>
</html>
26 changes: 14 additions & 12 deletions pages/docs/advanced_query.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ title: Advanced Query
layout: page
---

## Smart Select Fields
## <span id="smart_select">Smart Select Fields</span>

GORM allows select specific fields with [`Select`](query.html), if you often use this in your application, maybe you want to define a smaller API struct that select specific fields automatically
GORM allows select specific fields with [`Select`](query.html), 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:

```go
type User struct {
Expand All @@ -21,7 +21,7 @@ type APIUser struct {
Name string
}

// Select `id`, `name` automatically when query
// Select `id`, `name` automatically when querying
db.Model(&User{}).Limit(10).Find(&APIUser{})
// SELECT `id`, `name` FROM `users` LIMIT 10
```
Expand Down Expand Up @@ -58,7 +58,7 @@ db.Select("AVG(age) as avgage").Group("name").Having("AVG(age) > (?)", subQuery)

### <span id="from_subquery">From SubQuery</span>

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

```go
db.Table("(?) as u", DB.Model(&User{}).Select("name", "age")).Where("age = ?", 18}).Find(&User{})
Expand Down Expand Up @@ -112,7 +112,7 @@ DB.Table("users").Find(&results)

## FirstOrInit

Get first matched record, or initialize a new one with given conditions (only works with struct, map conditions)
Get first matched record or initialize a new instance with given conditions (only works with struct or map conditions)

```go
// User not found, initialize it with give conditions
Expand Down Expand Up @@ -147,7 +147,7 @@ db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 20}).FirstOrInit(&user)
// user -> User{ID: 111, Name: "Jinzhu", Age: 18}
```

`Assign` attributes to struct regardless it is found or not, those attributes won't be used to build SQL query
`Assign` attributes to struct regardless it is found or not, those attributes won't be used to build SQL query and the final data won't be saved into database

```go
// User not found, initialize it with give conditions and Assign attributes
Expand All @@ -162,7 +162,7 @@ db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 20}).FirstOrInit(&user)

## FirstOrCreate

Get first matched record, or create a new one with given conditions (only works with struct, map conditions)
Get first matched record or create a new one with given conditions (only works with struct, map conditions)

```go
// User not found, create a new record with give conditions
Expand All @@ -172,7 +172,7 @@ db.FirstOrCreate(&user, User{Name: "non_existing"})

// Found user with `name` = `jinzhu`
db.Where(User{Name: "jinzhu"}).FirstOrCreate(&user)
// user -> User{ID: 111, Name: "jinzhu", "Age}: 18
// user -> User{ID: 111, Name: "jinzhu", "Age": 18}
```

Create struct with more attributes if record not found, those `Attrs` won't be used to build SQL query
Expand All @@ -190,7 +190,7 @@ db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// user -> User{ID: 111, Name: "jinzhu", Age: 18}
```

`Assign` attributes to the record regardless it is found or not, and save them back to the database.
`Assign` attributes to the record regardless it is found or not and save them back to the database.

```go
// User not found, initialize it with give conditions and Assign attributes
Expand All @@ -208,7 +208,7 @@ db.Where(User{Name: "jinzhu"}).Assign(User{Age: 20}).FirstOrCreate(&user)

## Optimizer/Index Hints

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

```go
import "gorm.io/hints"
Expand Down Expand Up @@ -241,7 +241,7 @@ defer rows.Close()

for rows.Next() {
var user User
// ScanRows scan a row into 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
Expand Down Expand Up @@ -288,7 +288,7 @@ func (u *User) AfterFind(tx *gorm.DB) (err error) {

## <span id="pluck">Pluck</span>

Query single column from database and scan into a slice, if you want to query multiple columns, use [`Scan`](#scan) instead
Query single column from database and scan into a slice, if you want to query multiple columns, use `Select` with [`Scan`](query.html#scan) instead

```go
var ages []int64
Expand Down Expand Up @@ -341,6 +341,8 @@ db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(
// Find all paid, shipped orders that amount greater than 1000
```

Checout [Scopes](scopes.html) for details

## <span id="count">Count</span>

Get matched records count
Expand Down
31 changes: 17 additions & 14 deletions pages/docs/associations.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ layout: page

## Auto Create/Update

GORM will autosave associations and its reference using [Upsert](create.html#upsert) when creating/updating a record.
GORM will auto-save associations and its reference using [Upsert](create.html#upsert) when creating/updating a record.

```go
user := User{
Expand All @@ -24,15 +24,11 @@ user := User{

db.Create(&user)
// BEGIN TRANSACTION;
// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "addresses" (address1) VALUES ("Shipping Address - Address 1") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1"), ("Shipping Address - Address 1") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "users" (name,billing_address_id,shipping_address_id) VALUES ("jinzhu", 1, 2);
// INSERT INTO "emails" (user_id,email) VALUES (111, "[email protected]") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "emails" (user_id,email) VALUES (111, "[email protected]") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "languages" ("name") VALUES ('ZH') ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "user_languages" ("user_id","language_id") VALUES (111, 1) ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "languages" ("name") VALUES ('EN') ON DUPLICATE KEY DO NOTHING;
// INSERT INTO user_languages ("user_id","language_id") VALUES (111, 2) ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "emails" (user_id,email) VALUES (111, "[email protected]"), (111, "[email protected]") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "languages" ("name") VALUES ('ZH'), ('EN') ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "user_languages" ("user_id","language_id") VALUES (111, 1), (111, 2) ON DUPLICATE KEY DO NOTHING;
// COMMIT;

db.Save(&user)
Expand Down Expand Up @@ -77,7 +73,7 @@ var user User
db.Model(&user).Association("Languages")
// `user` is the source model, it must contains primary key
// `Languages` is a relationship's field name
// If the above two conditions matched, the AssociationMode should be started successfully, or it should return error
// If the above two requirements matched, the AssociationMode should be started successfully, or it should return error
db.Model(&user).Association("Languages").Error
```

Expand All @@ -87,8 +83,11 @@ Find matched associations

```go
db.Model(&user).Association("Languages").Find(&languages)
```

Find associations with conditions

// Find with conditions
```go
codes := []string{"zh-CN", "en-US", "ja-JP"}
db.Model(&user).Where("code IN ?", codes).Association("Languages").Find(&languages)

Expand Down Expand Up @@ -140,6 +139,10 @@ Return the count of current associations

```go
db.Model(&user).Association("Languages").Count()

// Count with conditions
codes := []string{"zh-CN", "en-US", "ja-JP"}
db.Model(&user).Where("code IN ?", codes).Association("Languages").Count()
```

### Batch Data
Expand All @@ -156,7 +159,7 @@ db.Model(&users).Association("Team").Delete(&userA)
// Get unduplicated count of members in all user's team
db.Model(&users).Association("Team").Count()

// For `Append`, `Replace` with batch data, arguments's length need to equal to data's length or will returns error
// For `Append`, `Replace` with batch data, arguments's length need to equal to data's length or will return error
var users = []User{user1, user2, user3}
// e.g: we have 3 users, Append userA to user1's team, append userB to user2's team, append userA, userB and userC to user3's team
db.Model(&users).Association("Team").Append(&userA, &userB, &[]User{userA, userB, userC})
Expand All @@ -174,5 +177,5 @@ db.Model(&users).Association("Team").Replace(&userA, &userB, &[]User{userA, user
| polymorphicValue | Specifies polymorphic value, default table name |
| many2many | Specifies join table name |
| jointForeignKey | Specifies foreign key of jointable |
| joinReferences | Specifies references' foreign key of jointable |
| constraint | Relations constraint |
| joinReferences | Specifies references' foreign key of jointable |
| constraint | Relations constraint, e.g: `OnUpdate`,`OnDelete`|
2 changes: 1 addition & 1 deletion pages/docs/belongs_to.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ GORM allows eager loading belongs to associations with `Preload` or `Joins`, ref

## FOREIGN KEY Constraints

You can setup `OnUpdate`, `OnDelete` constraints with tag `constraint`, for example:
You can setup `OnUpdate`, `OnDelete` constraints with tag `constraint`, it will be created when migrating with GORM, for example:

```go
type User struct {
Expand Down
2 changes: 1 addition & 1 deletion pages/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ GORM 2.0 is a rewrite from scratch, it introduces some incompatible-API change a
* Full self-reference relationships supports, Join Table improvements, Association Mode for batch data
* Multiple fields support for tracking create/update time, which adds support for UNIX (milli/nano) seconds
* Field permissions support: read-only, write-only, create-only, update-only, ignored
* New plugin system: read/write splitting with plugin Database Resolver, prometheus integrations...
* New plugin system: multiple databases, read/write splitting support with plugin Database Resolver, prometheus integrations...
* New Hooks API: unified interface with plugins
* New Migrator: allows to create database foreign keys for relationships, constraints/checker support, enhanced index support
* New Logger: context support, improved extensibility
Expand Down
4 changes: 1 addition & 3 deletions pages/docs/connecting_to_the_database.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ db, err := gorm.Open(mysql.New(mysql.Config{
DisableDatetimePrecision: true, // disable datetime precision, which not supported before MySQL 5.6
DontSupportRenameIndex: true, // drop & create when rename index, rename index not supported before MySQL 5.7, MariaDB
DontSupportRenameColumn: true, // `change` when rename column, rename column not supported before MySQL 8, MariaDB
SkipInitializeWithVersion: false, // auto configure based on used version
SkipInitializeWithVersion: false, // auto configure based on currently MySQL version
}), &gorm.Config{})
```

Expand Down Expand Up @@ -152,8 +152,6 @@ dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
db, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{})
```

Microsoft offers [a guide](https://sqlchoice.azurewebsites.net/en-us/sql-server/developer-get-started/) for using SQL Server with Go (and GORM).

## Connection Pool

GORM using [database/sql]((https://pkg.go.dev/database/sql) to maintain connection pool
Expand Down
2 changes: 1 addition & 1 deletion pages/docs/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ r.Get("/user", func(w http.ResponseWriter, r *http.Request) {

## Logger

Logger accepts `Context` too, you can it tracking logs, refer [Logger](logger.html) for details
Logger accepts `Context` too, you can use it for log tracking, refer [Logger](logger.html) for details
19 changes: 15 additions & 4 deletions pages/docs/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (User) TableName() string {
}
```

**NOTE** `TableName` doesn't allow dynamic name, its result will be cached for future, to use dynamic name, you can use the following code:
**NOTE** `TableName` doesn't allow dynamic name, its result will be cached for future, to use dynamic name, you can use `Scopes`, for example:

```go
func UserTable(user User) func (db *gorm.DB) *gorm.DB {
Expand Down Expand Up @@ -84,7 +84,7 @@ Check out [From SubQuery](advanced_query.html#from_subquery) for how to use SubQ

### <span id="naming_strategy">NamingStrategy</span>

GORM allows users change the default naming conventions by overriding the default `NamingStrategy`, which is used to build `TableName`, `ColumnName`, `JoinTableName`, `RelationshipFKName`, `CheckerName`, `IndexName`, Check out [GORM Config](gorm_config.html) for details
GORM allows users change the default naming conventions by overriding the default `NamingStrategy`, which is used to build `TableName`, `ColumnName`, `JoinTableName`, `RelationshipFKName`, `CheckerName`, `IndexName`, Check out [GORM Config](gorm_config.html#naming_strategy) for details

## Column Name

Expand All @@ -99,7 +99,7 @@ type User struct {
}
```

You can override the column name with tag `column`, or use [`NamingStrategy`](#naming_strategy)
You can override the column name with tag `column` or use [`NamingStrategy`](#naming_strategy)

```go
type Animal struct {
Expand All @@ -118,6 +118,9 @@ For models having `CreatedAt` field, the field will be set to the current time w
```go
db.Create(&user) // set `CreatedAt` to current time

user2 := User{Name: "jinzhu", CreatedAt: time.Now()}
db.Create(&user2) // user2's `CreatedAt` won't be changed

// To change its value, you could use `Update`
db.Model(&user).Update("CreatedAt", time.Now())
```
Expand All @@ -130,6 +133,14 @@ For models having `UpdatedAt` field, the field will be set to the current time w
db.Save(&user) // set `UpdatedAt` to current time

db.Model(&user).Update("name", "jinzhu") // will set `UpdatedAt` to current time

db.Model(&user).UpdateColumn("name", "jinzhu") // `UpdatedAt` won't be changed

user2 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Create(&user2) // user2's `UpdatedAt` won't be changed when creating

user3 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Save(&user3) // user3's `UpdatedAt` will change to current time when updating
```

**NOTE** GORM supports having multiple time tracking fields, track with other fields or track with UNIX second/UNIX nanosecond, check [Models](models.html#time_tracking) for more details
**NOTE** GORM supports having multiple time tracking fields and track with UNIX (nano/milli) seconds, checkout [Models](models.html#time_tracking) for more details
10 changes: 5 additions & 5 deletions pages/docs/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ for _, user := range users {
}
```

[Upsert](#upsert), [Create With Associations](#create_with_associations) supported for batch insert also
Batch Insert is also supported when using [Upsert](#upsert) and [Create With Associations](#create_with_associations)

## Create From Map

Expand All @@ -83,7 +83,7 @@ DB.Model(&User{}).Create([]map[string]interface{}{

### <span id="create_with_associations">Create With Associations</span>

If your model defined any relations, and it has non-zero relations, those data will be saved when creating
When creating some data with associations, if its associations value is not zero-value, those associations will be upserted, and its `Hooks` methods will be invoked.

```go
type CreditCard struct {
Expand All @@ -106,7 +106,7 @@ db.Create(&User{
// INSERT INTO `credit_cards` ...
```

You can skip saving associations with `Select`, `Omit`
You can skip saving associations with `Select`, `Omit`, for example:

```go
db.Omit("CreditCard").Create(&user)
Expand All @@ -122,13 +122,13 @@ You can define default values for fields with tag `default`, for example:
```go
type User struct {
ID int64
Name string `gorm:"default:'galeone'"`
Name string `gorm:"default:galeone"`
Age int64 `gorm:"default:18"`
uuid.UUID UUID `gorm:"type:uuid;default:gen_random_uuid()"` // db func
}
```

Then the default value will be used when inserting into the database for [zero-value](https://tour.golang.org/basics/12) fields
Then the default value *will be used* when inserting into the database for [zero-value](https://tour.golang.org/basics/12) fields

**NOTE** Any zero value like `0`, `''`, `false` won't be saved into the database for those fields defined default value, you might want to use pointer type or Scanner/Valuer to avoid this, for example:

Expand Down
8 changes: 4 additions & 4 deletions pages/docs/data_types.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Data Types
title: Customize Data Types
layout: page
---

Expand Down Expand Up @@ -40,7 +40,7 @@ func (j JSON) Value() (driver.Value, error) {

### GormDataTypeInterface

A customized data type might has different database types, you can implements the `GormDataTypeInterface` to set them up, for example:
A customized data type might has different database types for databases, you can implements the `GormDataTypeInterface` to set them up, for example:

```go
type GormDataTypeInterface interface {
Expand All @@ -64,15 +64,15 @@ func (JSON) GormDBDataType(db *gorm.DB, field *schema.Field) string {

### Clause Expression

Customized data type possible needs specifically SQL which can't use current GORM API, you can define a `Builder` to implement interface `clause.Expression`
Customized data type possible needs specifically SQL which can't use current GORM API, you can define a `Builder` method for the struct to implement interface `clause.Expression`

```go
type Expression interface {
Build(builder Builder)
}
```

Checkout [JSON](https://github.com/go-gorm/datatypes/blob/master/json.go) for implementation details
Checkout [JSON](https://github.com/go-gorm/datatypes/blob/master/json.go) for implementation details, usage:

```go
// Generates SQL with clause Expression
Expand Down
Loading

0 comments on commit b28fc19

Please sign in to comment.