アノテーション構文

アノテーションはインターフェースのメソッドに記述するコメントです。Genはそれらを解析し、適用された構造体に対するクエリAPIを生成します。

Genは動的な条件付きSQLをサポートするためのいくつかの規則を提供しています。それらを3つの側面から紹介します。

  • 結果の返却
  • テンプレートプレースホルダー
  • テンプレート式

結果の返却

Genでは、返される結果の型を設定できます。現在、以下の4つの基本型がサポートされています。

オプション 説明
gen.T 構造体を返します
gen.M マップを返します
gen.RowsAffected データベースから返された影響を受けた行数を返します(型:int64)
error エラーがあればエラーを返します

type Querier interface {
// SELECT * FROM @@table WHERE id=@id
GetByID(id int) (gen.T, error) // returns struct and error

// SELECT * FROM @@table WHERE id=@id
GetByID(id int) gen.T // returns data as struct

// SELECT * FROM @@table WHERE id=@id
GetByID(id int) (gen.M, error) // returns map and error

// INSERT INTO @@table (name, age) VALUES (@name, @age)
InsertValue(name string, age int) (gen.RowsAffected, error) // returns affected rows count and error
}

これらの基本型は、*[] などの他の記号と組み合わせることができます。例えば

type Querier interface {
// SELECT * FROM @@table WHERE id=@id
GetByID(id int) (*gen.T, error) // returns data as pointer and error

// SELECT * FROM @@table WHERE id=@id
GetByID(id int) (*[]gen.T, error) // returns data as pointer of slice and error

// SELECT * FROM @@table WHERE id=@id
GetByID(id int) ([]*gen.T, error) // returns data as slice of pointer and error

// SELECT * FROM @@table WHERE id=@id
GetByID(id int) ([]gen.M, error) // returns data as slice of map and error
}

テンプレートプレースホルダー

Genは動的で安全なSQLを生成するためのプレースホルダーを提供します。

名前 説明
@@table エスケープおよびクォートされたテーブル名
@@<name> パラメータからエスケープおよびクォートされたテーブル/列名
@<name> パラメータからのSQLクエリパラメータ

type Filter interface {
// SELECT * FROM @@table WHERE @@column=@value
FilterWithColumn(column string, value string) (gen.T, error)
}

// Apply the `Filter` interface to `User`, `Company`
g.ApplyInterface(func(Filter) {}, model.User{}, model.Company{})

コードを生成した後、アプリケーションで次のように使用できます。

import "your_project/query"

func main() {
user, err := query.User.FilterWithColumn("name", "jinzhu")
// similar like db.Exec("SELECT * FROM `users` WHERE `name` = ?", "jinzhu")

company, err := query.Company.FilterWithColumn("name", "tiktok")
// similar like db.Exec("SELECT * FROM `companies` WHERE `name` = ?", "tiktok")
}

テンプレート式

Genは動的条件付きSQLのための強力な式サポートを提供します。現在、以下の式がサポートされています。

  • if/else
  • where
  • set
  • for

if/else

if/else式では、条件としてgolang構文を使用できます。次のように記述できます。

{{if cond1}}
// do something here
{{else if cond2}}
// do something here
{{else}}
// do something here
{{end}}

例えば

type Querier interface {
// SELECT * FROM users WHERE
// {{if name !=""}}
// username=@name AND
// {{end}}
// role="admin"
QueryWith(name string) (gen.T,error)
}

より複雑なケース

type Querier interface {
// SELECT * FROM users
// {{if user != nil}}
// {{if user.ID > 0}}
// WHERE id=@user.ID
// {{else if user.Name != ""}}
// WHERE username=@user.Name
// {{end}}
// {{end}}
QueryWith(user *gen.T) (gen.T, error)
}

使用方法

query.User.QueryWith(&User{Name: "zhangqiang"})
// SELECT * FROM users WHERE username="zhangqiang"

where

where式を使用すると、SQLクエリのWHERE句を簡単に記述できます。簡単な例を見てみましょう。

type Querier interface {
// SELECT * FROM @@table
// {{where}}
// id=@id
// {{end}}
Query(id int) gen.T
}

生成されたコードでは、次のように使用できます。

query.User.Query(10)
// SELECT * FROM users WHERE id=10

別の複雑なケースを紹介します。このケースでは、子式が一致した場合にのみWHERE句が挿入され、where句内の不要なandorxor,をスマートに削除できることを学びます。

type Querier interface {
// SELECT * FROM @@table
// {{where}}
// {{if !start.IsZero()}}
// created_time > @start
// {{end}}
// {{if !end.IsZero()}}
// AND created_time < @end
// {{end}}
// {{end}}
FilterWithTime(start, end time.Time) ([]gen.T, error)
}

生成されたコードは次のように使用できます。

var (
since = time.Date(2022, 10, 1, 0, 0, 0, 0, time.UTC)
end = time.Date(2022, 10, 10, 0, 0, 0, 0, time.UTC)
zero = time.Time{}
)

query.User.FilterWithTime(since, end)
// SELECT * FROM `users` WHERE created_time > "2022-10-01" AND created_time < "2022-10-10"

query.User.FilterWithTime(since, zero)
// SELECT * FROM `users` WHERE created_time > "2022-10-01"

query.User.FilterWithTime(zero, end)
// SELECT * FROM `users` WHERE created_time < "2022-10-10"

query.User.FilterWithTime(zero, zero)
// SELECT * FROM `users`

set

set式は、SQLクエリのSET句を生成するために使用されます。不要な,を自動的に削除します。例えば

// UPDATE @@table
// {{set}}
// {{if user.Name != ""}} username=@user.Name, {{end}}
// {{if user.Age > 0}} age=@user.Age, {{end}}
// {{if user.Age >= 18}} is_adult=1 {{else}} is_adult=0 {{end}}
// {{end}}
// WHERE id=@id
Update(user gen.T, id int) (gen.RowsAffected, error)

生成されたコードは次のように使用できます。

query.User.Update(User{Name: "jinzhu", Age: 18}, 10)
// UPDATE users SET username="jinzhu", age=18, is_adult=1 WHERE id=10

query.User.Update(User{Name: "jinzhu", Age: 0}, 10)
// UPDATE users SET username="jinzhu", is_adult=0 WHERE id=10

query.User.Update(User{Age: 0}, 10)
// UPDATE users SET is_adult=0 WHERE id=10

for

for式はスライスを反復処理してSQLを生成します。例で説明しましょう。

// SELECT * FROM @@table
// {{where}}
// {{for _,user:=range users}}
// {{if user.Name !="" && user.Age >0}}
// (username = @user.Name AND age=@user.Age AND role LIKE concat("%",@user.Role,"%")) OR
// {{end}}
// {{end}}
// {{end}}
Filter(users []gen.T) ([]gen.T, error)

使用方法

query.User.Filter([]User{
{Name: "jinzhu", Age: 18, Role: "admin"},
{Name: "zhangqiang", Age: 18, Role: "admin"},
{Name: "modi", Age: 18, Role: "admin"},
{Name: "songyuan", Age: 18, Role: "admin"},
})
// SELECT * FROM users WHERE
// (username = "jinzhu" AND age=18 AND role LIKE concat("%","admin","%")) OR
// (username = "zhangqiang" AND age=18 AND role LIKE concat("%","admin","%"))
// (username = "modi" AND age=18 AND role LIKE concat("%","admin","%")) OR
// (username = "songyuan" AND age=18 AND role LIKE concat("%","admin","%"))

プラチナスポンサー

ゴールドスポンサー

プラチナスポンサー

ゴールドスポンサー