reiner

package module
v2.0.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2018 License: MIT Imports: 11 Imported by: 0

README

Reiner GoDoc Coverage Status Build Status Go Report Card

一個由 Golang 撰寫且比起部分 ORM 還要讚的 MySQL 指令建置函式庫。彈性高、不需要建構體標籤。實際上,這就只是 PHP-MySQLi-Database-Class 不過是用在 Golang 而已(但還是多了些功能)。

這是什麼?

萊納是一個由 Golang 撰寫的 MySQL 的指令建置函式庫(不是 ORM,永遠也不會是),幾乎所有東西都能操控於你手中。類似自己撰寫資料庫指令但是更簡單,JOIN 表格也變得比以前更方便了。

  • 幾乎全功能的函式庫。
  • 自動避免於 Goroutine 發生資料競爭的設計。
  • 支援 MySQL 複寫橫向擴展機制(區分讀/寫連線)。
  • 容易理解與記住、且使用方式十分簡單。
  • SQL 指令建構函式。
  • 資料庫表格建構協助函式。
  • 可串連的使用方式。
  • 支援子指令(Sub Query)。
  • 支援多樣的結果物件綁定(如:建構體切片)。
  • 可手動操作的交易機制(Transaction)和回溯(Rollback)功能。
  • 透過預置聲明(Prepared Statement),99.9% 避免 SQL 注入攻擊。

為什麼?

Gorm 已經是 Golang 裡的 ORM 典範,但實際上要操作複雜與關聯性高的 SQL 指令時並不是很合適,而 Reiner 解決了這個問題。Reiner 也試圖不要和建構體扯上關係,不希望使用者需要手動指定任何標籤在建構體中。

執行緒與併發安全性?

我們都知道 Golang 的目標就是併發程式,為了避免 Goroutine 導致資料競爭問題,Reiner 會在每有變更的時候自動複製 SQL 指令建置函式庫來避免所有併發程式共用同個 SQL 指令建置函式庫(此方式並不會使資料庫連線遞增而造成效能問題)。

在原先的舊版本中則需要手動透過 CopyClone 複製建置函式庫,這繁雜的手續正是重新設計的原因。但也因為如此,現在 SQL 指令建置函式若需要分散串接則需要重新地不斷賦值,簡單來說就是像這樣。

package main

func main() {
	db, _ := reiner.New("...")

	// 在舊有的版本中原本能夠這樣直覺地分散串接一段 SQL 指令。
	// 注意!這是舊版本的做法,目前已經被廢除。
	db.Table("Users")
	if ... {
		db.Where("Username", "YamiOdymel")
	}
	if ... {
		db.Limit(1, 10)
	}
	db.Get()

	// 新的版本中因為 Reiner 會不斷地回傳一個新的建置資料函式,
	// 因此必須不斷地重新賦值。
	myDB := db.Table("Users")
	if ... {
		myDB = myDB.Where("Username", "YamiOdymel")
	}
	if ... {
		myDB = myDB.Limit(1, 10)
	}
	myDB, _ = myDB.Get()
}

效能如何?

這裡有份簡略化的效能測試報表。目前仍會持續優化並且增加快取以避免重複建置相同指令而費時。

測試規格:
1.7 GHz Intel Core i7 (4650U)
8 GB 1600 MHz DDR3

插入:Dbr > SQL > SQLx > Xorm > Reiner > Gorm
BenchmarkReinerInsert-4             3000            571298 ns/op            1719 B/op         49 allocs/op
BenchmarkSQLInsert-4                3000            429340 ns/op             901 B/op         17 allocs/op
BenchmarkDbrInsert-4                5000            413442 ns/op            2210 B/op         37 allocs/op
BenchmarkSQLxInsert-4               3000            444055 ns/op             902 B/op         17 allocs/op
BenchmarkGormInsert-4               2000            776838 ns/op            5319 B/op        101 allocs/op
BenchmarkXormInsert-4               3000            562341 ns/op            2921 B/op         64 allocs/op

選擇 100 筆資料:SQL > SQLx > Dbr > Reiner > Gorm > Xorm
BenchmarkReinerSelect100-4          2000            659189 ns/op           42907 B/op       1155 allocs/op
BenchmarkSQLSelect100-4             5000            336121 ns/op           28864 B/op        723 allocs/op
BenchmarkDbrSelect100-4             3000            529430 ns/op           87496 B/op       1638 allocs/op
BenchmarkSQLxSelect100-4            3000            376810 ns/op           32368 B/op        829 allocs/op
BenchmarkGormSelect100-4            2000            726107 ns/op          209236 B/op       3870 allocs/op
BenchmarkXormSelect100-4            2000            868688 ns/op          103358 B/op       4583 allocs/op

索引

安裝方式

打開終端機並且透過 go get 安裝此套件即可。

$ go get github.com/teacat/reiner

命名建議

在 Reiner 中為了配合 Golang 程式命名規範,我們建議你將所有事情以駝峰式大小寫命名,因為這能夠確保兩邊的風格相同。事實上,甚至連資料庫內的表格名稱、欄位名稱都該這麼做。當遇上 ipidurl 時,請遵循 Golang 的命名方式皆以大寫使用,如 AddrIPUserIDPhotoURL,而不是 AddrIpUserIdPhotoUrl

NULL 值

在 Golang 裏處理資料庫的 NULL 值向來都不是很方便,因此不建議允許資料庫中可有 NULL 欄位。基於 Reiner 底層的 go-sql-driver/mysql 因素,Reiner 並不會將接收到的 NULL 值轉換成指定型態的零值(Zero Value),這意味著當你從資料庫中取得一個可能為 NULL 值的字串,你必須透過 *string 或者 sql.NullString 而非普通的 string 型態(會發生 Scan 錯誤),實際用法像這樣。

type User struct {
	Username string
	Nickname sql.NullString
	Age 	 sql.NullInt64
}

// 然後綁定這個建構體到資料庫結果。
var u User
db.Table("Users").Bind(&u).GetOne()

// 輸出取得的結果。
if !u.Nickname.Valid() {
	panic("Nickname 的內容是 NULL!不可饒恕!")
}
fmt.Println(u.Nickname.Value)

使用方式

Reiner 的使用方式十分直覺與簡易,類似基本的 SQL 指令集但是更加地簡化了。

資料庫連線

首先你需要透過函式來將 Reiner 連上資料庫,如此一來才能夠初始化建置函式庫與相關的資料庫表格建構函式。一個最基本的單資料庫連線,讀寫都將透過此連線,連線字串共用於其它套件是基於 DSN(Data Source Name)。

import "github.com/teacat/reiner"

db, err := reiner.New("root:root@/test?charset=utf8")
if err != nil {
    panic(err)
}
水平擴展(讀/寫分離)

這種方式可以有好幾個主要資料庫、副從資料庫,這意味著寫入時都會流向到主要資料庫,而讀取時都會向副從資料庫請求。這很適合用在大型結構還有水平擴展上。當你有多個資料庫來源時,Reiner 會逐一遞詢每個資料庫來源,英文稱其為 Round Robin,也就是每個資料庫都會輪流呼叫而避免單個資料庫負荷過重,也不會有隨機呼叫的事情發生。

import "github.com/teacat/reiner"

db, err := reiner.New("root:root@/master?charset=utf8", []string{
	"root:root@/slave?charset=utf8",
	"root:root@/slave2?charset=utf8",
	"root:root@/slave3?charset=utf8",
})
if err != nil {
    panic(err)
}
SQL 建構模式

如果你已經有喜好的 SQL 資料庫處理套件,那麼你就可以在建立 Reiner 時不要傳入任何資料,這會使 Reiner 避免與資料庫互動,透過這個設計你可以將 Reiner 作為你的 SQL 指令建構函式。

// 當沒有傳入 MySQL 連線資料時,Reiner 僅會建置 SQL 執行指令而非與資料庫有實際互動。
builder, _ := reiner.New()
// 然後像這樣透過 Reiner 建立執行指令。
myQuery, _ := builder.Table("Users").Where("Username", "YamiOdymel").Get()

// 透過 `Query` 取得 Reiner 所建立的 Query 當作欲執行的資料庫指令。
sql.Prepare(myQuery.Query())
// 接著展開 `Params` 即是我們在 Reiner 中存放的值。
sql.Exec(myQuery.Params()...)
// 等效於:SELECT * FROM Users WHERE Username = ?

資料綁定與處理

Reiner 允許你將查詢結果映射到結構體切片或結構體。

var user []*User
db.Bind(&user).Table("Users").Get()

插入

透過 Reiner 你可以很輕鬆地透過建構體或是 map 來插入一筆資料。這是最傳統的插入方式,若該表格有自動遞增的編號欄位,插入後你就能透過 LastInsertID 獲得最後一次插入的編號。

db.Table("Users").Insert(map[string]interface{}{
	"Username": "YamiOdymel",
	"Password": "test",
})
// 等效於:INSERT INTO Users (Username, Password) VALUES (?, ?)
覆蓋

覆蓋的用法與插入相同,當有同筆資料時會先進行刪除,然後再插入一筆新的,這對有外鍵的表格來說十分危險。

db.Table("Users").Replace(map[string]interface{}{
	"Username": "YamiOdymel",
	"Password": "test",
})
// 等效於:REPLACE INTO Users (Username, Password) VALUES (?, ?)
函式

插入時你可以透過 Reiner 提供的函式來執行像是 SHA1() 或者取得目前時間的 NOW(),甚至將目前時間加上一年⋯等。

db.Table("Users").Insert(map[string]interface{}{
	"Username":  "YamiOdymel",
	"Password":  db.Func("SHA1(?)", "secretpassword+salt"),
	"Expires":   db.Now("+1Y"),
	"CreatedAt": db.Now(),
})
// 等效於:INSERT INTO Users (Username, Password, Expires, CreatedAt) VALUES (?, SHA1(?), NOW() + INTERVAL 1 YEAR, NOW())
當重複時

Reiner 支援了插入資料若重複時可以更新該筆資料的指定欄位>這類似「覆蓋」,但這並不會先刪除原先的資料,這種方式僅會在插入時檢查是否重複,若重複則更新該筆資料。

lastInsertID := "ID"
db.Table("Users").OnDuplicate([]string{"UpdatedAt"}, lastInsertID).Insert(map[string]interface{}{
	"Username":  "YamiOdymel",
	"Password":  "test",
	"UpdatedAt": db.Now(),
})
// 等效於:INSERT INTO Users (Username, Password, UpdatedAt) VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE UpdatedAt = VALUES(UpdatedAt)
多筆資料

Reiner 允許你透過 InsertMulti 同時間插入多筆資料(單指令插入多筆資料),這省去了透過迴圈不斷執行單筆插入的困擾,這種方式亦大幅度提升了效能。

data := []map[string]interface{}{
	{
		"Username": "YamiOdymel",
		"Password": "test",
	}, {
		"Username": "Karisu",
		"Password": "12345",
	},
}
db.Table("Users").InsertMulti(data)
// 等效於:INSERT INTO Users (Username, Password) VALUES (?, ?), (?, ?)

筆數限制

Limit 能夠限制 SQL 執行的筆數,如果是 10,那就表示只處理最前面 10 筆資料而非全部(例如:選擇、更新、移除)。

db.Table("Users").Limit(10).Update(data)
// 等效於:UPDATE Users SET ... LIMIT 10

更新

更新一筆資料在 Reiner 中極為簡單,你只需要指定表格名稱還有資料即可。

db.Table("Users").Where("Username", "YamiOdymel").Update(map[string]interface{}{
	"Username": "Karisu",
	"Password": "123456",
})
// 等效於:UPDATE Users SET Username = ?, Password = ? WHERE Username = ?

選擇與取得

最基本的選擇在 Reiner 中稱之為 Get 而不是 Select

db.Table("Users").Get()
// 等效於:SELECT * FROM Users
指定欄位

Get 中傳遞欄位名稱作為參數,多個欄位由逗點區分,亦能是函式。

db.Table("Users").Get("Username", "Nickname")
// 等效於:SELECT Username, Nickname FROM Users

db.Table("Users").Get("COUNT(*) AS Count")
// 等效於:SELECT COUNT(*) AS Count FROM Users
單行資料

通常多筆結果會映射到一個切片或是陣列,而 GetOne 可以取得單筆資料並將其結果映射到單個建構體或 map,令使用上更加方便。

當透過 map[string]interface{} 當作映射對象的時候,請注意資料庫並不會自動辨別 intstring 等資料型態,反倒有可能會是 int64[]uint8{[]byte},因此使用 map 時請多加注意在型態轉換上的部分。

var u User
db.Bind(&u).Table("Users").Where("ID", 1).GetOne()
// 等效於:SELECT * FROM Users WHERE ID = ? LIMIT 1

var d map[string]interface{}
db.Bind(&d).Table("Users").GetOne("SUM(ID) AS Sum", "COUNT(*) AS Count")
// 等效於:SELECT SUM(ID), COUNT(*) AS Count FROM Users LIMIT 1

fmt.Println(d["Sum"])
fmt.Println(d["Count"])
單欄位值

透過 GetValueGetValues 來取得單個欄位的內容。例如說:你想要單個使用者的暱稱,甚至是多個使用者的暱稱陣列就很適用。

// 取得多筆資料的 `Username` 欄位資料。
var us []string
db.Bind(&u).Table("Users").GetValues("Username")
// 等效於:SELECT Username FROM Users

// 取得單筆資料的某個欄位值。
var u string
db.Bind(&u).Table("Users").GetValue("Username")
// 等效於:SELECT Username FROM Users LIMIT 1

// 或者是函式。
var i int
db.Bind(&i).Table("Users").GetValue("COUNT(*)")
// 等效於:SELECT COUNT(*) FROM Users LIMIT 1
分頁功能

分頁就像是取得資料ㄧ樣,但更擅長用於多筆資料、不會一次顯示完畢的內容。Reiner 能夠幫你自動處理換頁功能,讓你不需要自行計算換頁時的筆數應該從何開始。為此,你需要定義兩個變數,一個是目前的頁數,另一個是單頁能有幾筆資料。

// 目前的頁數。
page := 1
// 設置一頁最多能有幾筆資料。
db.PageLimit = 10
db = db.Table("Users").Paginate(page)
// 等效於:SELECT SQL_CALC_FOUND_ROWS * FROM Users LIMIT 0, 10

fmt.Println("目前頁數為 %d,共有 %d 頁", page, db.TotalPages)

執行生指令

Reiner 已經提供了近乎日常中 80% 會用到的方式,但如果好死不死你想使用的功能在那 20% 之中,我們還提供了原生的方法能讓你直接輸入 SQL 指令執行自己想要的鳥東西。一個最基本的生指令(Raw Query)就像這樣。

其中亦能帶有預置聲明(Prepared Statement),也就是指令中的問號符號替代了原本的值。這能避免你的 SQL 指令遭受注入攻擊。

var us []User
db.Bind(&us).RawQuery("SELECT * FROM Users WHERE ID >= ?", 10)
單行資料

RawQueryOne 是個僅選擇單筆資料的生指令函式,這意味著你能夠將取得的資料映射到建構體或是 map 上。

var u User
db.Bind(&u).RawQueryOne("SELECT * FROM Users WHERE ID = ?", 10)
// 等效於:SELECT * FROM Users WHERE ID = ? LIMIT 1

var d map[string]interface{}
db.Bind(&d).RawQueryOne("SELECT SUM(ID), COUNT(*) AS Count FROM Users")
// 等效於:SELECT SUM(ID), COUNT(*) AS Count FROM Users LIMIT 1

fmt.Println(d["Sum"])
fmt.Println(d["Count"])
單欄位值

透過 RawQueryValueRawQueryValues 可以取得單個欄位的內容。例如說:你想要單個使用者的暱稱,甚至是多個使用者的暱稱陣列就很適用。

// 取得多筆資料的 `Username` 欄位資料。
var us []string
db.Bind(&us).RawQueryValues("SELECT Username FROM Users")

// 取得單筆資料的某個欄位值。
var pwd string
db.Bind(&pwd).RawQueryValue("SELECT Password FROM Users WHERE ID = ?", 10)
// 等效於:SELECT Password FROM Users WHERE ID = ? LIMIT 1

// 或者是函式。
var i int
db.Bind(&i).RawQueryValue("SELECT COUNT(*) FROM Users")
// 等效於:SELECT COUNT(*) FROM Users LIMIT 1
進階方式

如果你對 SQL 指令夠熟悉,你也可以使用更進階且複雜的用法。

db.RawQuery("SELECT ID, FirstName, LastName FROM Users WHERE ID = ? AND Username = ?", 1, "admin")

params := []int{10, 1, 10, 11, 2, 10}
query := (`
	(SELECT A FROM t1 WHERE A = ? AND B = ?)
	UNION ALL
	(SELECT A FROM t2 WHERE A = ? AND B = ?)
	UNION ALL
	(SELECT A FROM t3 WHERE A = ? AND B = ?)
`)
db.RawQuery(query, params...)

條件宣告

透過 Reiner 宣告 WHERE 條件也能夠很輕鬆。一個最基本的 WHERE AND 像這樣使用。

db.Table("Users").Where("ID", 1).Where("Username", "admin").Get()
// 等效於:SELECT * FROM Users WHERE ID = ? AND Username = ?
擁有

HAVING 能夠與 WHERE 一同使用。

db.Table("Users").Where("ID", 1).Having("Username", "admin").Get()
// 等效於:SELECT * FROM Users WHERE ID = ? HAVING Username = ?
欄位比較

如果你想要在條件中宣告某個欄位是否等於某個欄位⋯你能夠像這樣。

// 別這樣。
db.Table("Users").Where("LastLogin", "CreatedAt").Get()
// 這樣才對。
db.Table("Users").Where("LastLogin = CreatedAt").Get()
// 等效於:SELECT * FROM Users WHERE LastLogin = CreatedAt
自訂運算子

WhereHaving 中,你可以自訂條件的運算子,如 >=、<=、<>⋯等。

db.Table("Users").Where("ID", ">=", 50).Get()
// 等效於:SELECT * FROM Users WHERE ID >= ?
介於/不介於

條件也可以用來限制數值內容是否在某數之間(相反之,也能夠限制是否不在某範圍內)。

db.Table("Users").Where("ID", "BETWEEN", 0, 20).Get()
// 等效於:SELECT * FROM Users WHERE ID BETWEEN ? AND ?
於清單/不於清單內

條件能夠限制並確保取得的內容不在(或者在)指定清單內。

db.Table("Users").Where("ID", "IN", 1, 5, 27, -1, "d").Get()
// 等效於:SELECT * FROM Users WHERE ID IN (?, ?, ?, ?, ?)

list := []interface{}{1, 5, 27, -1, "d"}
db.Table("Users").Where("ID", "IN", list...).Get()
// 等效於:SELECT * FROM Users WHERE ID IN (?, ?, ?, ?, ?)
或/還有或

通常來說多個 Where 會產生 AND 條件,這意味著所有條件都必須符合,有些時候你只希望符合部分條件即可,就能夠用上 OrWhere

db.Table("Users").Where("FirstNamte", "John").OrWhere("FirstNamte", "Peter").Get()
// 等效於:SELECT * FROM Users WHERE FirstName = ? OR FirstName = ?

如果你的要求比較多,希望達到「A = B 或者 (A = C 或 A = D)」的話,你可以嘗試這樣。

db.Table("Users").Where("A = B").OrWhere("(A = C OR A = D)").Get()
// 等效於:SELECT * FROM Users WHERE A = B OR (A = C OR A = D)
空值

確定某個欄位是否為空值。

// 別這樣。
db.Table("Users").Where("LastName", "NULL").Get()
// 這樣才對。
db.Table("Users").Where("LastName", "IS", nil).Get()
// 等效於:SELECT * FROM Users WHERE LastName IS NULL
時間戳

Unix Timestamp 是一項將日期與時間秒數換算成數字的格式(範例:1498001308),這令你能夠輕易地換算其秒數,但當你要判斷時間是否為某一年、月、日,甚至範圍的時候就會有些許困難,而 Reiner 也替你想到了這一點。

需要注意的是 Reiner 中的 Timestamp 工具無法串聯使用,這意味著當你想要確認時間戳是否為某年某月時,你需要有兩個 Where 條件,而不行使用 IsYear().IsMonth()。更多的用法可以在原生文件中找到,這裡僅列出不完全的範例供大略參考。

日期

判斷是否為特定年、月、日、星期或完整日期。

t := db.Timestamp

db.Table("Users").Where("CreatedAt", t.IsDate("2017-07-13")).Get()
// 等效於:SELECT * FROM Users WHERE DATE(FROM_UNIXTIME(CreatedAt)) = ?

db.Table("Users").Where("CreatedAt", t.IsYear(2017)).Get()
// 等效於:SELECT * FROM Users WHERE YEAR(FROM_UNIXTIME(CreatedAt)) = ?

db.Table("Users").Where("CreatedAt", t.IsMonth(1)).Get()
db.Table("Users").Where("CreatedAt", t.IsMonth("January")).Get()
// 等效於:SELECT * FROM Users WHERE MONTH(FROM_UNIXTIME(CreatedAt)) = ?

db.Table("Users").Where("CreatedAt", t.IsDay(16)).Get()
// 等效於:SELECT * FROM Users WHERE DAY(FROM_UNIXTIME(CreatedAt)) = ?

db.Table("Users").Where("CreatedAt", t.IsWeekday(5)).Get()
db.Table("Users").Where("CreatedAt", t.IsWeekday("Friday")).Get()
// 等效於:SELECT * FROM Users WHERE WEEKDAY(FROM_UNIXTIME(CreatedAt)) = ?
時間

確定是否為特定時間。

t := db.Timestamp

db.Table("Users").Where("CreatedAt", t.IsHour(18)).Get()
// 等效於:SELECT * FROM Users WHERE HOUR(FROM_UNIXTIME(CreatedAt)) = ?

db.Table("Users").Where("CreatedAt", t.IsMinute(25)).Get()
// 等效於:SELECT * FROM Users WHERE MINUTE(FROM_UNIXTIME(CreatedAt)) = ?

db.Table("Users").Where("CreatedAt", t.IsSecond(16)).Get()
// 等效於:SELECT * FROM Users WHERE SECOND(FROM_UNIXTIME(CreatedAt)) = ?

db.Table("Users").Where("CreatedAt", t.IsWeekday(5)).Get()
// 等效於:SELECT * FROM Users WHERE WEEKDAY(FROM_UNIXTIME(CreatedAt)) = ?
生條件

你也能夠直接在條件中輸入指令。

db.Table("Users").Where("ID != CompanyID").Where("DATE(CreatedAt) = DATE(LastLogin)").Get()
// 等效於:SELECT * FROM Users WHERE ID != CompanyID AND DATE(CreatedAt) = DATE(LastLogin)
條件變數

生條件中可以透過 ? 符號,並且在後面傳入自訂變數。

db.Table("Users").Where("(ID = ? OR ID = ?)", 6, 2).Where("Login", "Mike").Get()
// 等效於:SELECT * FROM Users WHERE (ID = ? OR ID = ?) AND Login = ?

刪除

刪除一筆資料再簡單不過了,透過 Count 計數能夠清楚知道你的 SQL 指令影響了幾行資料,如果是零的話即是無刪除任何資料。

var err error
db, err = db.Table("Users").Where("ID", 1).Delete()
if count := db.Count(); err == nil && count != 0 {
    fmt.Printf("成功地刪除了 %d 筆資料!", count)
}
// 等效於:DELETE FROM Users WHERE ID = ?

排序

Reiner 亦支援排序功能,如遞增或遞減,亦能擺放函式。

db.Table("Users").OrderBy("ID", "ASC").OrderBy("Login", "DESC").OrderBy("RAND()").Get()
// 等效於:SELECT * FROM Users ORDER BY ID ASC, Login DESC, RAND()
從值排序

也能夠從值進行排序,只需要傳入一個切片即可。

db.Table("Users").OrderBy("UserGroup", "ASC", "SuperUser", "Admin", "Users").Get()
// 等效於:SELECT * FROM Users ORDER BY FIELD (UserGroup, ?, ?, ?) ASC

群組

簡單的透過 GroupBy 就能夠將資料由指定欄位群組排序。

db.Table("Users").GroupBy("Name").Get()
// 等效於:SELECT * FROM Users GROUP BY Name

加入

Reiner 支援多種表格加入方式,如:InnerJoinLeftJoinRightJoinNaturalJoinCrossJoin

db.
	Table("Products").
	LeftJoin("Users", "Products.TenantID = Users.TenantID").
	Where("Users.ID", 6).
	Get("Users.Name", "Products.ProductName")
// 等效於:SELECT Users.Name, Products.ProductName FROM Products AS Products LEFT JOIN Users AS Users ON (Products.TenantID = Users.TenantID) WHERE Users.ID = ?
條件限制

你亦能透過 JoinWhereJoinOrWhere 擴展表格加入的限制條件。

db.
	Table("Products").
	LeftJoin("Users", "Products.TenantID = Users.TenantID").
	JoinOrWhere("Users", "Users.TenantID", 5).
	Get("Users.Name", "Products.ProductName")
// 等效於:SELECT Users.Name, Products.ProductName FROM Products AS Products LEFT JOIN Users AS Users ON (Products.TenantID = Users.TenantID OR Users.TenantID = ?)

子指令

Reiner 支援複雜的子指令,欲要建立一個子指令請透過 SubQuery 函式,這將會建立一個不能被執行的資料庫建置函式庫,令你可以透過 GetUpdate 等建立相關 SQL 指令,但不會被資料庫執行。將其帶入到一個正常的資料庫函式中即可成為子指令。

subQuery := db.SubQuery().Table("Users").Get()
// 等效於不會被執行的:SELECT * FROM Users
選擇/取得

你能夠輕易地將子指令放置在選擇/取得指令中。

subQuery := db.SubQuery().Table("Products").Where("Quantity", ">", 2).Get("UserID")

db.Table("Users").Where("ID", "IN", subQuery).Get()
// 等效於:SELECT * FROM Users WHERE ID IN (SELECT UserID FROM Products WHERE Quantity > ?)
插入

插入新資料時也可以使用子指令。

subQuery := db.SubQuery().Table("Users").Where("ID", 6).Get("Name")

db.Table("Products").Insert(map[string]interface{}{
	"ProductName": "測試商品",
	"UserID":      subQuery,
	"LastUpdated": db.Now(),
})
// 等效於:INSERT INTO Products (ProductName, UserID, LastUpdated) VALUES (?, (SELECT Name FROM Users WHERE ID = 6), NOW())
加入

就算是加入表格的時候也可以用上子指令,但你需要為子指令建立別名。

subQuery := db.SubQuery("Users").Table("Users").Where("Active", 1).Get()

db.
	Table("Products").
	LeftJoin(subQuery, "Products.UserID = U.ID").
	Get("Users.Username", "Products.ProductName")
// 等效於:SELECT Users.Username, Products.ProductName FROM Products AS Products LEFT JOIN (SELECT * FROM Users WHERE Active = ?) AS Users ON Products.UserID = Users.ID
存在/不存在

你同時也能夠透過子指令來確定某筆資料是否存在。

subQuery := db.SubQuery().Table("Users").Where("Company", "測試公司").Get("UserID")

db.Table("Products").Where(subQuery, "EXISTS").Get()
// 等效於:SELECT * FROM Products WHERE EXISTS (SELECT UserID FROM Users WHERE Company = ?)

是否擁有該筆資料

有些時候我們只想知道資料庫是否有符合的資料,但並不是要取得其資料,舉例來說就像是登入是僅是要確認帳號密碼是否吻合,此時就可以透過 Has 用來確定資料庫是否有這筆資料。

has, err := db.Table("Users").Where("Username", "yamiodymel").Where("Password", "123456").Has()
if has {
	fmt.Println("登入成功!")
} else {
	fmt.Println("帳號或密碼錯誤。")
}

輔助函式

Reiner 有提供一些輔助用的函式協助你除錯、紀錄,或者更加地得心應手。

資料庫連線

透過 Disconnect 結束一段連線。

if err := db.Disconnect(); err != nil {
	panic(err)
}

你也能在資料庫發生錯誤、連線遺失時透過 Connect 來重新手動連線。

if err := db.Ping(); err != nil {
	db.Connect()
}
最後執行的 SQL 指令

取得最後一次所執行的 SQL 指令,這能夠用來記錄你所執行的所有動作。

db = db.Table("Users").Get()
fmt.Println("最後一次執行的 SQL 指令是:%s", db.LastQuery)
// 輸出:SELECT * FROM Users
結果/影響的行數

行數很常用於檢查是否有資料、作出變更。資料庫不會因為沒有變更任何資料而回傳一個錯誤(資料庫僅會在真正發生錯誤時回傳錯誤資料),所以這是很好的檢查方法。

db, _ = db.Table("Users").Get()
fmt.Println("總共獲取 %s 筆資料", db.Count())
db, _ = db.Table("Users").Delete()
fmt.Println("總共刪除 %s 筆資料", db.Count())
db, _ = db.Table("Users").Update(data)
fmt.Println("總共更新 %s 筆資料", db.Count())
最後插入的編號

當插入一筆新的資料,而該表格帶有自動遞增的欄位時,就能透過 LastInsertID 取得最新一筆資料的編號。

var id int

db, _ = db.Table("Users").Insert(data)
id = db.LastInsertID

如果你是經由 InsertMulti 同時間插入多筆資料,基於 MySQL 底層的設定,你並沒有辦法透過 LastInsertID 取得剛才插入的所有資料編號。如果你仍希望取得插入編號,請透過迴圈不斷地執行 Insert 並保存其 LastInsertID 資料。

var ids []int

for ... {
	var err error
	db, err = db.Table("Users").Insert(data)
	if err != nil {
		ids = append(ids, db.LastInsertID)
	}
}
總筆數

如果你想取得這個指令總共能夠取得多少筆資料,透過 WithTotalCount 就能夠啟用總筆數查詢,這可能會稍微降低一點資料庫效能。

db, _ = db.Table("Users").WithTotalCount().Get()
fmt.Println(db.TotalCount)

交易函式

交易函式僅限於 InnoDB 型態的資料表格,這能令你的資料寫入更加安全。你可以透過 Begin 開始記錄並繼續你的資料庫寫入行為,如果途中發生錯誤,你能透過 Rollback 回到紀錄之前的狀態,即為回溯(或滾回、退回),如果這筆交易已經沒有問題了,透過 Commit 將這次的變更永久地儲存到資料庫中。

// 當交易開始時請使用回傳的 `tx` 而不是原先的 `db`,這樣才能確保交易繼續。
tx, err := db.Begin()
if err != nil {
	panic(err)
}

// 如果插入資料時發生錯誤,則呼叫 `Rollback()` 回到交易剛開始的時候。
if _, err = tx.Table("Wallets").Insert(data); err != nil {
	tx.Rollback()
	panic(err)
}
if _, err = tx.Table("Users").Insert(data); err != nil {
	tx.Rollback()
	panic(err)
}

// 透過 `Commit()` 確保上列變更都已經永久地儲存到資料庫。
if err := tx.Commit(); err != nil {
	panic(err)
}

鎖定表格

你能夠手動鎖定資料表格,避免同時間寫入相同資料而發生錯誤。

db.Table("Users").SetLockMethod("WRITE").Lock()

// 呼叫其他的 Lock() 函式也會自動將前一個上鎖解鎖,當然你也可以手動呼叫 Unlock() 解鎖。
db.Unlock()
// 等效於:UNLOCK TABLES

// 同時間要鎖上兩個表格也很簡單。
db.Table("Users", "Logs").SetLockMethod("READ").Lock()
// 等效於:LOCK TABLES Users READ, Logs READ

指令關鍵字

Reiner 也支援設置指令關鍵字。

db.Table("Users").SetQueryOption("LOW_PRIORITY").Insert(data)
// 等效於:INSERT LOW_PRIORITY INTO Users ...

db.Table("Users").SetQueryOption("FOR UPDATE").Get()
// 等效於:SELECT * FROM Users FOR UPDATE

db.Table("Users").SetQueryOption("SQL_NO_CACHE").Get()
// 等效於:SELECT SQL_NO_CACHE * FROM Users
多個選項

你亦能同時設置多個關鍵字給同個指令。

db.Table("Users").SetQueryOption("LOW_PRIORITY", "IGNORE").Insert(data)
// Gives: INSERT LOW_PRIORITY IGNORE INTO Users ...

效能追蹤

這會降低執行效能,但透過追蹤功能能夠有效地得知每個指令所花費的執行時間和建置指令,並且取得相關執行檔案路徑與行號。

db = db.SetTrace(true).Table("Users").Get()
fmt.Printf("%+v", db.Traces[0])

//[{Query:SELECT * FROM Users Duration:808.698µs Stacks:[map
//[File:/Users/YamiOdymel/go/src/github.com/teacat/reiner/builder.go Line:559 Skip:0 PC:19399228] map[Line:666 Skip:1 PC:19405153 //File:/Users/YamiOdymel/go/src/github.com/teacat/reiner/builder.go] map[Skip:2 PC:19407043 //File:/Users/YamiOdymel/go/src/github.com/teacat/reiner/builder.go Line:705] map[Line:74 Skip:3 PC:19548011 //File:/Users/YamiOdymel/go/src/github.com/teacat/reiner/builder.go] map[PC:17610310 //File:/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go Line:657 Skip:4] map
//[File:/usr/local/Cellar/go/1.8/libexec/src/runtime/asm_amd64.s Line:2197 Skip:5 PC:17143345]] Error:<nil>}]

表格建構函式

Reiner 除了基本的資料庫函式可供使用外,還能夠建立一個表格並且規劃其索引、外鍵、型態。

migration := db.Migration()

migration.Table("Users").Column("Username").Varchar(32).Primary().Create()
// 等效於:CREATE TABLE Users (Username VARCHAR(32) NOT NULL PRIMARY KEY) ENGINE=INNODB
數值 字串 二進制 檔案資料 時間 浮點數 固組
TinyInt Char Binary Blob Date Double Enum
SmallInt Varchar VarBinary MediumBlob DateTime Decimal Set
MediumInt TinyText Bit LongBlob Time Float
Int Text Timestamp
BigInt MediumText Year
LongText

相關連結

這裡是 Reiner 受啟發,或是和資料庫有所關聯的連結。

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidPointer 是會在資料的映射目的地為 nil 指標時所發生的錯誤。
	ErrInvalidPointer = errors.New("reiner: the destination of the result is an invalid pointer")
	// ErrIncorrectDataType 是個會在插入、更新資料時傳入非 `map[string]interface` 資料型態參數時所發生的錯誤。
	ErrIncorrectDataType = errors.New("reiner: the data type must be a `map[string]interface`")
	// ErrUnbegunTransaction 會在執行尚未透過 `Begin` 初始化的交易時所發生的錯誤。
	ErrUnbegunTransaction = errors.New("reiner: calling the transaction function without `Begin()`")
	// ErrNoTable 是個會在未指定資料表格時所發生的錯誤。
	ErrNoTable = errors.New("reiner: no table was specified")
)

Functions

This section is empty.

Types

type Builder

type Builder struct {

	// Timestamp 是時間戳的相關輔助函式。
	Timestamp *Timestamp
	// Traces 是最後執行的 SQL 指令蹤跡資訊,適合用於效能除錯上。
	Traces []Trace
	// TotalCount 是結果的總計筆數。
	TotalCount int
	// PageLimit 限制了一頁僅能有幾筆資料。
	PageLimit int
	// TotalPage 是結果的總計頁數。
	TotalPage int
	// LasyQuery 是最後所執行的 SQL 指令。
	LastQuery string
	// LastInsertID 是最後所插入的資料 ID 編號。
	LastInsertID int
	// LastParams 是最後執行時的參數資料。
	LastParams []interface{}
	// LastResult 是最後執行時的 `sql.Result` 資料。
	LastResult sql.Result
	// contains filtered or unexported fields
}

Builder 是個資料庫的 SQL 指令建置系統,同時也帶有資料庫的連線資料。

func New

func New(dataSourceNames ...interface{}) (*Builder, error)

New 會建立一個新的連線並且提供 MySQL 的 SQL 指令建置系統。當沒有傳入參數時, 會變成 SQL 指令建置模式,而這個情況下你可以透過 Reiner 來建立 SQL 查詢指令。

.New()

如果要連接到一個資料庫,第一個參數則需要傳入主要資料庫的 DSN(資料來源名稱)。

.New("root:root@/master")

若需要讀/寫區分,第一個參數則是為主要資料庫的 DSN,而其餘的則是 Slave 資料庫的 DSN。

.New("root:root@/master", root:root@/slave")
.New("root:root@/master", []string{"root:root@/slave", "root:root@/slave2"})

查看 https://dev.mysql.com/doc/refman/5.7/en/replication-solutions-scaleout.html 了解更多資訊。

func (*Builder) Begin

func (b *Builder) Begin() (builder *Builder, err error)

Begin 會開始一個新的交易。

func (*Builder) Bind

func (b *Builder) Bind(destination interface{}) (builder *Builder)

Bind 會設置資料的映射目的地,這樣就能在 SQL 指令執行後將資料映射到某個變數、記憶體指標。

func (*Builder) Commit

func (b *Builder) Commit() error

Commit 會讓交易中所產生的資料異動成為永久紀錄並保存於資料庫中且結束交易。

func (*Builder) Connect

func (b *Builder) Connect() (err error)

Connect 會試圖在斷線之後重新連線至資料庫。

func (*Builder) Count

func (b *Builder) Count() (count int)

Count 會回傳查詢的結果行數。

func (*Builder) Delete

func (b *Builder) Delete() (builder *Builder, err error)

Delete 會移除相符的資料列,記得用上 `Where` 條件式來避免整個資料表格被清空。 這很重要好嗎,因為⋯你懂的⋯。喔,不。

func (*Builder) Disconnect

func (b *Builder) Disconnect() (err error)

Disconnect 會結束目前的資料庫連線。

func (*Builder) Func

func (b *Builder) Func(query string, data ...interface{}) Function

Func 會基於參數來返回一個新的 SQL 資料庫函式, 這能夠當作函式放置於查詢指令中,而不會被當作普通的資料執行。

func (*Builder) Get

func (b *Builder) Get(columns ...string) (builder *Builder, err error)

Get 會取得多列的資料結果,傳入的參數為欲取得的欄位名稱,不傳入參數表示取得所有欄位。

func (*Builder) GetOne

func (b *Builder) GetOne(columns ...string) (builder *Builder, err error)

GetOne 會取得僅單列的資料作為結果,傳入的參數為欲取得的欄位名稱,不傳入參數表示取得所有欄位。 簡單說,這就是 `.Limit(1).Get()` 的縮寫用法。

func (*Builder) GetValue

func (b *Builder) GetValue(column string) (builder *Builder, err error)

GetValue 會取得單個欄位的資料(例如:字串、正整數)。

func (*Builder) GetValues

func (b *Builder) GetValues(column string) (builder *Builder, err error)

GetValues 會取得將多筆單個欄位的資料映射到本地的字串、正整數切片、陣列。

func (*Builder) GroupBy

func (b *Builder) GroupBy(columns ...string) (builder *Builder)

GroupBy 會在執行 SQL 指令時依照特定的欄位來做執行區分。

func (*Builder) Has

func (b *Builder) Has() (builder *Builder, has bool, err error)

Has 會在有查詢結果時回傳 `true`,這很適合用於一些資料驗證的時機(例如:使用者名稱是否已存在⋯等)。

func (*Builder) Having

func (b *Builder) Having(args ...interface{}) (builder *Builder)

Having 會增加一個 `HAVING AND` 條件式。

func (*Builder) InnerJoin

func (b *Builder) InnerJoin(table interface{}, condition string) (builder *Builder)

InnerJoin 會內部插入一個資料表格。

func (*Builder) Insert

func (b *Builder) Insert(data interface{}) (builder *Builder, err error)

Insert 會插入一筆新的資料。

func (*Builder) InsertMulti

func (b *Builder) InsertMulti(data interface{}) (builder *Builder, err error)

InsertMulti 會一次插入多筆資料。

func (*Builder) JoinOrWhere

func (b *Builder) JoinOrWhere(table interface{}, args ...interface{}) (builder *Builder)

JoinOrWhere 能夠建立一個基於 `WHERE OR` 的條件式給某個指定的插入資料表格。

func (*Builder) JoinWhere

func (b *Builder) JoinWhere(table interface{}, args ...interface{}) (builder *Builder)

JoinWhere 能夠建立一個基於 `WHERE AND` 的條件式給某個指定的插入資料表格。

func (*Builder) LeftJoin

func (b *Builder) LeftJoin(table interface{}, condition string) (builder *Builder)

LeftJoin 會向左插入一個資料表格。

func (*Builder) Limit

func (b *Builder) Limit(from int, count ...int) (builder *Builder)

Limit 能夠在 SQL 查詢指令中建立限制筆數的條件。

func (*Builder) Lock

func (b *Builder) Lock(tableNames ...string) (builder *Builder, err error)

Lock 會以指定的上鎖方式來鎖定某個指定的資料表格,這能用以避免資料競爭問題。

func (*Builder) Migration

func (b *Builder) Migration() *Migration

Migration 會返回一個新的資料表格遷移建構體。 主要是基於現有的資料庫連線來提供資料表格與欄位的的操作功能。

func (*Builder) NaturalJoin

func (b *Builder) NaturalJoin(table interface{}, condition string) (builder *Builder)

NaturalJoin 會自然插入一個資料表格。

func (*Builder) Now

func (b *Builder) Now(formats ...string) Function

Now 會回傳一個基於 `INTERVAL` 的 SQL 資料庫函式, 傳入的參數格式可以是 `+1Y`、`-2M`,同時也可以像 `Now("+1Y", "-2M")` 一樣地串連使用。 支援的格式為:`Y`(年)、`M`(月)、`D`(日)、`W`(星期)、`h`(小時)、`m`(分鐘)、`s`(秒數)。

func (*Builder) OnDuplicate

func (b *Builder) OnDuplicate(columns []string, lastInsertID ...string) (builder *Builder)

OnDuplicate 能夠指定欲更新的欄位名稱,這會在插入的資料重複時自動更新相對應的欄位。

func (*Builder) OrHaving

func (b *Builder) OrHaving(args ...interface{}) (builder *Builder)

OrHaving 會增加一個 `HAVING OR` 條件式。

func (*Builder) OrWhere

func (b *Builder) OrWhere(args ...interface{}) (builder *Builder)

OrWhere 會增加一個 `WHERE OR` 條件式。

func (*Builder) OrderBy

func (b *Builder) OrderBy(column string, args ...interface{}) (builder *Builder)

OrderBy 會依照指定的欄位來替結果做出排序(例如:`DESC`、`ASC`)。

func (*Builder) Paginate

func (b *Builder) Paginate(pageCount int, columns ...string) (builder *Builder, err error)

Paginate 基本上和 `Get` 取得函式無異,但此函式能夠自動依照分頁數來推算該從哪裡繼續取得資料。 使用時須先確定是否有指定 `PageLimit`(預設為:20),這樣才能限制一頁有多少筆資料。

func (*Builder) Params

func (b *Builder) Params() (params []interface{})

Params returns the last used parameters, it's the same as `LastParams` but the name is more meaningful.

func (*Builder) Ping

func (b *Builder) Ping() (err error)

Ping 會以 ping 來檢查資料庫連線。

func (*Builder) Query

func (b *Builder) Query() (query string)

Query 會回傳最後一次所建置的 SQL 執行指令,這和 `LastQuery` 相同功能但這函式的名稱可能更符合某些場合。

func (*Builder) RawQuery

func (b *Builder) RawQuery(query string, values ...interface{}) (builder *Builder, err error)

RawQuery 會接收傳入的變數來執行傳入的 SQL 執行語句,變數可以在語句中以 `?`(Prepared Statements)使用來避免 SQL 注入攻擊。 這會將多筆資料映射到本地的建構體切片、陣列上。

func (*Builder) RawQueryOne

func (b *Builder) RawQueryOne(query string, values ...interface{}) (builder *Builder, err error)

RawQueryOne 與 RawQuery 使用方法相同,但這會在 SQL 指令後追加 `LIMIT 1` 且僅會將單筆資料映射到本地的建構體、`map`。

func (*Builder) RawQueryValue

func (b *Builder) RawQueryValue(query string, values ...interface{}) (builder *Builder, err error)

RawQueryValue 與 RawQuery 使用方法相同,但這會在 SQL 指令後追加 `LIMIT 1` 並將單個欄位的資料映射到本地的變數(字串、正整數), 這很適合用於像是你想要取得單個使用者暱稱的時候。

func (*Builder) RawQueryValues

func (b *Builder) RawQueryValues(query string, values ...interface{}) (builder *Builder, err error)

RawQueryValues 與 RawQuery 使用方法相同,但這會將多筆單個欄位的資料映射到本地的字串、正整數切片、陣列。 這很適合用於像是你想要取得多個使用者暱稱陣列的時候。

func (*Builder) Replace

func (b *Builder) Replace(data interface{}) (builder *Builder, err error)

Replace 基本上和 `Insert` 無異,這會在有重複資料時移除該筆資料並重新插入。 若無該筆資料則插入新的資料。

func (*Builder) RightJoin

func (b *Builder) RightJoin(table interface{}, condition string) (builder *Builder)

RightJoin 會向右插入一個資料表格。

func (*Builder) Rollback

func (b *Builder) Rollback() error

Rollback 能夠回溯到交易剛開始的時候,並且在不保存資料變動的情況下結束交易。

func (*Builder) SetLockMethod

func (b *Builder) SetLockMethod(method string) (builder *Builder)

SetLockMethod 會設置鎖定資料表格的方式(例如:`WRITE`、`READ`)。

func (*Builder) SetQueryOption

func (b *Builder) SetQueryOption(options ...string) (builder *Builder)

SetQueryOption 會設置 SQL 指令的額外選項(例如:`SQL_NO_CACHE`)。

func (*Builder) SetTrace

func (b *Builder) SetTrace(status bool) (builder *Builder)

SetTrace 會決定蹤跡模式的開關,當設置為 `true` 時會稍微地拖慢效能, 但你就能夠從 `Trace` 屬性中取得 SQL 執行後的堆疊與路徑結果。

func (*Builder) SubQuery

func (b *Builder) SubQuery(alias ...string) (subQuery *SubQuery)

SubQuery 能夠將目前的 SQL 指令轉換為子指令(Sub Query)來防止建置後直接被執行,這讓你可以將子指令傳入其他的條件式(例如:`WHERE`), 若欲將子指令傳入插入(Join)條件中,必須在參數指定此子指令的別名。

func (*Builder) Table

func (b *Builder) Table(tableName ...string) (builder *Builder)

Table 能夠指定資料表格的名稱。

func (*Builder) Unlock

func (b *Builder) Unlock(tableNames ...string) (builder *Builder, err error)

Unlock 能解鎖已鎖上的資料表格。

func (*Builder) Update

func (b *Builder) Update(data interface{}) (builder *Builder, err error)

Update 會以指定的資料來更新相對應的資料列。

func (*Builder) Where

func (b *Builder) Where(args ...interface{}) (builder *Builder)

Where 會增加一個 `WHERE AND` 條件式。

func (*Builder) WithTotalCount

func (b *Builder) WithTotalCount() (builder *Builder)

WithTotalCount 會在 SQL 執行指令中安插 `SQL_CALC_FOUND_ROWS` 選項, 如此一來就能夠在執行完 SQL 指令後取得查詢的總計行數。在不同情況下,這可能會拖低執行效能。

type CharsetType

type CharsetType string

CharsetType 是資料表的字符集格式。

const (
	// CharsetBig5 是用於資料庫表格的 `big5` 字符集。
	CharsetBig5 CharsetType = "big5"
	// CharsetDEC8 是用於資料庫表格的 `dec8` 字符集。
	CharsetDEC8 CharsetType = "dec8"
	// CharsetCP850 是用於資料庫表格的 `cp850` 字符集。
	CharsetCP850 CharsetType = "cp850"
	// CharsetHP8 是用於資料庫表格的 `hp8` 字符集。
	CharsetHP8 CharsetType = "hp8"
	// CharsetKOI8R 是用於資料庫表格的 `koi8r` 字符集。
	CharsetKOI8R CharsetType = "koi8r"
	// CharsetLatin1 是用於資料庫表格的 `latin1` 字符集。
	CharsetLatin1 CharsetType = "latin1"
	// CharsetLatin2 是用於資料庫表格的 `latin2` 字符集。
	CharsetLatin2 CharsetType = "latin2"
	// CharsetSwe7 是用於資料庫表格的 `swe7` 字符集。
	CharsetSwe7 CharsetType = "swe7"
	// CharsetASCII 是用於資料庫表格的 `ascii` 字符集。
	CharsetASCII CharsetType = "ascii"
	// CharsetUJIS 是用於資料庫表格的 `ujis` 字符集。
	CharsetUJIS CharsetType = "ujis"
	// CharsetSJIS 是用於資料庫表格的 `sjis` 字符集。
	CharsetSJIS CharsetType = "sjis"
	// CharsetHebrew 是用於資料庫表格的 `hebrew` 字符集。
	CharsetHebrew CharsetType = "hebrew"
	// CharsetTIS620 是用於資料庫表格的 `tis620` 字符集。
	CharsetTIS620 CharsetType = "tis620"
	// CharsetEUCKR 是用於資料庫表格的 `euckr` 字符集。
	CharsetEUCKR CharsetType = "euckr"
	// CharsetKOI8U 是用於資料庫表格的 `koi8u` 字符集。
	CharsetKOI8U CharsetType = "koi8u"
	// CharsetGB2312 是用於資料庫表格的 `gb2312` 字符集。
	CharsetGB2312 CharsetType = "gb2312"
	// CharsetGreek 是用於資料庫表格的 `greek` 字符集。
	CharsetGreek CharsetType = "greek"
	// CharsetCP1250 是用於資料庫表格的 `cp1250` 字符集。
	CharsetCP1250 CharsetType = "cp1250"
	// CharsetGBK 是用於資料庫表格的 `gbk` 字符集。
	CharsetGBK CharsetType = "gbk"
	// CharsetLatin5 是用於資料庫表格的 `latin5` 字符集。
	CharsetLatin5 CharsetType = "latin5"
	// CharsetARMSCII8 是用於資料庫表格的 `armscii8` 字符集。
	CharsetARMSCII8 CharsetType = "armscii8"
	// CharsetUTF8 是用於資料庫表格的 `utf8` 字符集。
	CharsetUTF8 CharsetType = "utf8"
	// CharsetUCS2 是用於資料庫表格的 `ucs2` 字符集。
	CharsetUCS2 CharsetType = "ucs2"
	// CharsetCP866 是用於資料庫表格的 `cp866` 字符集。
	CharsetCP866 CharsetType = "cp866"
	// CharsetKeybcs2 是用於資料庫表格的 `keybcs2` 字符集。
	CharsetKeybcs2 CharsetType = "keybcs2"
	// CharsetMacCE 是用於資料庫表格的 `macce` 字符集。
	CharsetMacCE CharsetType = "macce"
	// CharsetMacRoman 是用於資料庫表格的 `macroman` 字符集。
	CharsetMacRoman CharsetType = "macroman"
	// CharsetCP852 是用於資料庫表格的 `cp852` 字符集。
	CharsetCP852 CharsetType = "cp852"
	// CharsetLatin7 是用於資料庫表格的 `latin7` 字符集。
	CharsetLatin7 CharsetType = "latin7"
	// CharsetUTF8MB4 是用於資料庫表格的 `utf8mb4` 字符集。
	CharsetUTF8MB4 CharsetType = "utf8mb4"
	// CharsetCP1251 是用於資料庫表格的 `cp1251` 字符集。
	CharsetCP1251 CharsetType = "cp1251"
	// CharsetUTF16 是用於資料庫表格的 `utf16` 字符集。
	CharsetUTF16 CharsetType = "utf16"
	// CharsetCP1256 是用於資料庫表格的 `cp1256` 字符集。
	CharsetCP1256 CharsetType = "cp1256"
	// CharsetCP1257 是用於資料庫表格的 `cp1257` 字符集。
	CharsetCP1257 CharsetType = "cp1257"
	// CharsetUTF32 是用於資料庫表格的 `utf32` 字符集。
	CharsetUTF32 CharsetType = "utf32"
	// CharsetBinary 是用於資料庫表格的 `binary` 字符集。
	CharsetBinary CharsetType = "binary"
	// CharsetGEOSTD8 是用於資料庫表格的 `geostd8` 字符集。
	CharsetGEOSTD8 CharsetType = "geostd8"
	// CharsetCP932 是用於資料庫表格的 `cp932` 字符集。
	CharsetCP932 CharsetType = "cp932"
	// CharsetEUCJPMS 是用於資料庫表格的 `eucjpms` 字符集。
	CharsetEUCJPMS CharsetType = "eucjpms"
)

type CollationType

type CollationType string

CollationType 是資料表的字符校對格式。

const (
	// CollationBig5 是用於資料庫表格的 `big5_chinese_ci` 字符校對格式。
	CollationBig5 CollationType = "big5_chinese_ci"
	// CollationDEC8 是用於資料庫表格的 `dec8_swedish_ci` 字符校對格式。
	CollationDEC8 CollationType = "dec8_swedish_ci"
	// CollationCP850 是用於資料庫表格的 `cp850_general_ci` 字符校對格式。
	CollationCP850 CollationType = "cp850_general_ci"
	// CollationHP8 是用於資料庫表格的 `hp8_english_ci` 字符校對格式。
	CollationHP8 CollationType = "hp8_english_ci"
	// CollationKOI8R 是用於資料庫表格的 `koi8r_general_ci` 字符校對格式。
	CollationKOI8R CollationType = "koi8r_general_ci"
	// CollationLatin1 是用於資料庫表格的 `latin1_swedish_ci` 字符校對格式。
	CollationLatin1 CollationType = "latin1_swedish_ci"
	// CollationLatin2 是用於資料庫表格的 `latin2_general_ci` 字符校對格式。
	CollationLatin2 CollationType = "latin2_general_ci"
	// CollationSwe7 是用於資料庫表格的 `swe7_swedish_ci` 字符校對格式。
	CollationSwe7 CollationType = "swe7_swedish_ci"
	// CollationASCII 是用於資料庫表格的 `ascii_general_ci` 字符校對格式。
	CollationASCII CollationType = "ascii_general_ci"
	// CollationUJIS 是用於資料庫表格的 `ujis_japanese_ci` 字符校對格式。
	CollationUJIS CollationType = "ujis_japanese_ci"
	// CollationSJIS 是用於資料庫表格的 `sjis_japanese_ci` 字符校對格式。
	CollationSJIS CollationType = "sjis_japanese_ci"
	// CollationHebrew 是用於資料庫表格的 `hebrew_general_ci` 字符校對格式。
	CollationHebrew CollationType = "hebrew_general_ci"
	// CollationTIS620 是用於資料庫表格的 `tis620_thai_ci` 字符校對格式。
	CollationTIS620 CollationType = "tis620_thai_ci"
	// CollationEUCKR 是用於資料庫表格的 `euckr_korean_ci` 字符校對格式。
	CollationEUCKR CollationType = "euckr_korean_ci"
	// CollationKOI8U 是用於資料庫表格的 `koi8u_general_ci` 字符校對格式。
	CollationKOI8U CollationType = "koi8u_general_ci"
	// CollationGB2312 是用於資料庫表格的 `gb2312_chinese_ci` 字符校對格式。
	CollationGB2312 CollationType = "gb2312_chinese_ci"
	// CollationGreek 是用於資料庫表格的 `greek_general_ci` 字符校對格式。
	CollationGreek CollationType = "greek_general_ci"
	// CollationCP1250 是用於資料庫表格的 `cp1250_general_ci` 字符校對格式。
	CollationCP1250 CollationType = "cp1250_general_ci"
	// CollationGBK 是用於資料庫表格的 `gbk_chinese_ci` 字符校對格式。
	CollationGBK CollationType = "gbk_chinese_ci"
	// CollationLatin5 是用於資料庫表格的 `latin5_turkish_ci` 字符校對格式。
	CollationLatin5 CollationType = "latin5_turkish_ci"
	// CollationARMSCII8 是用於資料庫表格的 `armscii8_general_ci` 字符校對格式。
	CollationARMSCII8 CollationType = "armscii8_general_ci"
	// CollationUTF8 是用於資料庫表格的 `utf8_general_ci` 字符校對格式。
	CollationUTF8 CollationType = "utf8_general_ci"
	// CollationUCS2 是用於資料庫表格的 `ucs2_general_ci` 字符校對格式。
	CollationUCS2 CollationType = "ucs2_general_ci"
	// CollationCP866 是用於資料庫表格的 `cp866_general_ci` 字符校對格式。
	CollationCP866 CollationType = "cp866_general_ci"
	// CollationKeybcs2 是用於資料庫表格的 `keybcs2_general_ci` 字符校對格式。
	CollationKeybcs2 CollationType = "keybcs2_general_ci"
	// CollationMacCE 是用於資料庫表格的 `macce_general_ci` 字符校對格式。
	CollationMacCE CollationType = "macce_general_ci"
	// CollationMacRoman 是用於資料庫表格的 `macroman_general_ci` 字符校對格式。
	CollationMacRoman CollationType = "macroman_general_ci"
	// CollationCP852 是用於資料庫表格的 `cp852_general_ci` 字符校對格式。
	CollationCP852 CollationType = "cp852_general_ci"
	// CollationLatin7 是用於資料庫表格的 `latin7_general_ci` 字符校對格式。
	CollationLatin7 CollationType = "latin7_general_ci"
	// CollationUTF8MB4 是用於資料庫表格的 `utf8mb4_general_ci` 字符校對格式。
	CollationUTF8MB4 CollationType = "utf8mb4_general_ci"
	// CollationCP1251 是用於資料庫表格的 `cp1251_general_ci` 字符校對格式。
	CollationCP1251 CollationType = "cp1251_general_ci"
	// CollationUTF16 是用於資料庫表格的 `utf16_general_ci` 字符校對格式。
	CollationUTF16 CollationType = "utf16_general_ci"
	// CollationCP1256 是用於資料庫表格的 `cp1256_general_ci` 字符校對格式。
	CollationCP1256 CollationType = "cp1256_general_ci"
	// CollationCP1257 是用於資料庫表格的 `cp1257_general_ci` 字符校對格式。
	CollationCP1257 CollationType = "cp1257_general_ci"
	// CollationUTF32 是用於資料庫表格的 `utf32_general_ci` 字符校對格式。
	CollationUTF32 CollationType = "utf32_general_ci"
	// CollationBinary 是用於資料庫表格的 `binary` 字符校對格式。
	CollationBinary CollationType = "binary"
	// CollationGEOSTD8 是用於資料庫表格的 `geostd8_general_ci` 字符校對格式。
	CollationGEOSTD8 CollationType = "geostd8_general_ci"
	// CollationCP932 是用於資料庫表格的 `cp932_japanese_ci` 字符校對格式。
	CollationCP932 CollationType = "cp932_japanese_ci"
	// CollationEUCJPMS 是用於資料庫表格的 `eucjpms_japanese_ci` 字符校對格式。
	CollationEUCJPMS CollationType = "eucjpms_japanese_ci"
)

type DB

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

DB 是一個擁有許多連線的資料庫來源。

type EngineType

type EngineType string

EngineType 是資料表的引擎格式。

const (
	// EngineInnoDB 是用於資料庫表格的 `InnoDB` 引擎格式。
	EngineInnoDB EngineType = "innodb"
	// EngineMyISAM 是用於資料庫表格的 `MyISAM` 引擎格式。
	EngineMyISAM EngineType = "myisam"
)

type Function

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

Function 重現了一個像 `SHA(?)` 或 `NOW()` 的資料庫函式。

type Migration

type Migration struct {

	// LasyQuery 是最後一次所執行的 SQL 指令。
	LastQuery string
	// contains filtered or unexported fields
}

Migration 是一個資料庫表格的遷移系統。

func (*Migration) AutoIncrement

func (m *Migration) AutoIncrement() *Migration

AutoIncrement 會將最後一個欄位設置為自動遞增,這僅能用於正整數欄位上。

func (*Migration) BigInt

func (m *Migration) BigInt(length int) *Migration

BigInt 會將最後一個欲建立的欄位資料型態設置為 `bigint`。

func (*Migration) Binary

func (m *Migration) Binary(length int) *Migration

Binary 會將最後一個欲建立的欄位資料型態設置為 `binary`。

func (*Migration) Bit

func (m *Migration) Bit(length int) *Migration

Bit 會將最後一個欲建立的欄位資料型態設置為 `bit`。

func (*Migration) Blob

func (m *Migration) Blob() *Migration

Blob 會將最後一個欲建立的欄位資料型態設置為 `blob`。

func (*Migration) Char

func (m *Migration) Char(length int) *Migration

Char 會將最後一個欲建立的欄位資料型態設置為 `char`。

func (*Migration) Charset

func (m *Migration) Charset(charset CharsetType) *Migration

Charset 會設置資料表格的字符集。

func (*Migration) Collation

func (m *Migration) Collation(collation CollationType) *Migration

Collation 會設置資料表格的字符校對格式。

func (*Migration) Column

func (m *Migration) Column(name string) *Migration

Column 會建立一個新的欄位。

func (*Migration) Comment

func (m *Migration) Comment(text string) *Migration

Comment 能夠替最後一個欄位設置說明。

func (*Migration) Create

func (m *Migration) Create() (err error)

Create 會執行先前的所有設置並且建立出一個相對應資料表格與其中的所有欄位。

func (*Migration) Date

func (m *Migration) Date() *Migration

Date 會將最後一個欲建立的欄位資料型態設置為 `date`。

func (*Migration) DateTime

func (m *Migration) DateTime() *Migration

DateTime 會將最後一個欲建立的欄位資料型態設置為 `datetime`。

func (*Migration) Decimal

func (m *Migration) Decimal(length ...int) *Migration

Decimal 會將最後一個欲建立的欄位資料型態設置為 `decimal`。

.Decimal(2, 1)

func (*Migration) Default

func (m *Migration) Default(value interface{}) *Migration

Default 能夠替最後一個欄位設置預設值,可以是 nil、字串、正整數或者 `CURRENT_TIMESTAMP` 和 `NOW()`。

func (*Migration) Double

func (m *Migration) Double(length ...int) *Migration

Double 會將最後一個欲建立的欄位資料型態設置為 `double`。

func (*Migration) Drop

func (m *Migration) Drop(tableNames ...string) error

Drop 會移除指定的資料表格,並在找不到資料表格時回傳錯誤。

func (*Migration) DropIfExists

func (m *Migration) DropIfExists(tableNames ...string) error

DropIfExists 會移除指定的資料表格,若指定的資料表格存在的話。

func (*Migration) Engine

func (m *Migration) Engine(engine EngineType) *Migration

Engine 能夠設置資料表的引擎種類。

func (*Migration) Enum

func (m *Migration) Enum(types ...interface{}) *Migration

Enum 會將最後一個欲建立的欄位資料型態設置為 `enum`。

.Enum(1, 2, "A", "B")

func (*Migration) Float

func (m *Migration) Float(length ...int) *Migration

Float 會將最後一個欲建立的欄位資料型態設置為 `float`。

.Float(2, 1)
.Float(1)

func (*Migration) Foreign

func (m *Migration) Foreign(args ...interface{}) *Migration

Foreign 會將最後一個欄位設置為外鍵,或者是建立一個匿名/命名群組。 欲將最後一個欄位設置為外鍵欄位可以這麼做:

Columns("id").Foreign("users.id")

欲建立一個匿名的外鍵群組則是像這樣:

.Foreign([]string{"id", "username"}, []string{"users.id", "users.username"})

而一個命名的外鍵群組,第一個參數則是群組的名稱,其他參數與匿名群組無異。

.Foreign("fk_group", []string{"id", "username"}, []string{"users.id", "users.username"})

func (*Migration) Index

func (m *Migration) Index(args ...interface{}) *Migration

Index 會在沒有參數的情況下將某個欄位設定為索引。

.Column("id").Index()

當傳入的參數是一個字串切片時,會將這些欄位名稱作為索引群組。

.Index([]string{"id", "username"})

當第一個參數是字串,第二個則是字串切片時則會建立一個命名的索引群組。

.Index("ik_group", []string{"id", "username"})

func (*Migration) Int

func (m *Migration) Int(length int) *Migration

Int 會將最後一個欲建立的欄位資料型態設置為 `int`。

func (*Migration) LongBlob

func (m *Migration) LongBlob() *Migration

LongBlob 會將最後一個欲建立的欄位資料型態設置為 `longblob`。

func (*Migration) LongText

func (m *Migration) LongText() *Migration

LongText 會將最後一個欲建立的欄位資料型態設置為 `longtext`。

func (*Migration) MediumBlob

func (m *Migration) MediumBlob() *Migration

MediumBlob 會將最後一個欲建立的欄位資料型態設置為 `mediumblob`。

func (*Migration) MediumInt

func (m *Migration) MediumInt(length int) *Migration

MediumInt 會將最後一個欲建立的欄位資料型態設置為 `mediumint`。

func (*Migration) MediumText

func (m *Migration) MediumText() *Migration

MediumText 會將最後一個欲建立的欄位資料型態設置為 `mediumtext`。

func (*Migration) Nullable

func (m *Migration) Nullable() *Migration

Nullable 會將最後一個欄位設置為允許空值。

func (*Migration) OnDelete

func (m *Migration) OnDelete(action string) *Migration

OnDelete 能夠決定外鍵資料被刪除時,相關欄位該做什麼處置(例如:`NO ACTION`、`SET NULL`、等)。

func (*Migration) OnUpdate

func (m *Migration) OnUpdate(action string) *Migration

OnUpdate 能夠決定外鍵資料變更時,相關欄位該做什麼處置(例如:`NO ACTION`、`SET NULL`、等)。

func (*Migration) Primary

func (m *Migration) Primary(args ...interface{}) *Migration

Primary 會在沒有參數的情況下將某個欄位設定為主鍵。

.Column("id").Primary()

當傳入的參數是一個字串切片時,會將這些欄位名稱作為主鍵群組。

.Primary([]string{"id", "username"})

當第一個參數是字串,第二個則是字串切片時則會建立一個命名的主鍵群組。

.Primary("pk_group", []string{"id", "username"})

func (*Migration) Set

func (m *Migration) Set(types ...interface{}) *Migration

Set 會將最後一個欲建立的欄位資料型態設置為 `set`。

.Set(1, 2, "A", "B")

func (*Migration) SmallInt

func (m *Migration) SmallInt(length int) *Migration

SmallInt 會將最後一個欲建立的欄位資料型態設置為 `smallint`。

func (*Migration) Table

func (m *Migration) Table(tableName string, comment ...string) *Migration

Table 會準備一個資料表格供後續建立。

func (*Migration) Text

func (m *Migration) Text() *Migration

Text 會將最後一個欲建立的欄位資料型態設置為 `text`。

func (*Migration) Time

func (m *Migration) Time() *Migration

Time 會將最後一個欲建立的欄位資料型態設置為 `time`。

func (*Migration) Timestamp

func (m *Migration) Timestamp() *Migration

Timestamp 會將最後一個欲建立的欄位資料型態設置為 `timestamp`。

func (*Migration) TinyBlob

func (m *Migration) TinyBlob() *Migration

TinyBlob 會將最後一個欲建立的欄位資料型態設置為 `tinyblob`。

func (*Migration) TinyInt

func (m *Migration) TinyInt(length int) *Migration

TinyInt 會將最後一個欲建立的欄位資料型態設置為 `tinyint`。

func (*Migration) TinyText

func (m *Migration) TinyText() *Migration

TinyText 會將最後一個欲建立的欄位資料型態設置為 `tinytext`。

func (*Migration) Unique

func (m *Migration) Unique(args ...interface{}) *Migration

Unique 會在沒有參數的情況下將某個欄位設定為不重覆鍵。

.Column("id").Unique()

當傳入的參數是一個字串切片時,會將這些欄位名稱作為不重覆鍵群組。

.Unique([]string{"id", "username"})

當第一個參數是字串,第二個則是字串切片時則會建立一個命名的不重覆鍵群組。

.Unique("uk_group", []string{"id", "username"})

func (*Migration) Unsigned

func (m *Migration) Unsigned() *Migration

Unsigned 會將最後一個欄位設置為非負數欄位。

func (*Migration) VarBinary

func (m *Migration) VarBinary(length int) *Migration

VarBinary 會將最後一個欲建立的欄位資料型態設置為 `varbinary`。

func (*Migration) Varchar

func (m *Migration) Varchar(length int) *Migration

Varchar 會將最後一個欲建立的欄位資料型態設置為 `varchar`。

func (*Migration) Year

func (m *Migration) Year() *Migration

Year 會將最後一個欲建立的欄位資料型態設置為 `year`。

type SubQuery

type SubQuery struct {

	// PageLimit 限制了一頁僅能有幾筆資料。
	PageLimit int
	// contains filtered or unexported fields
}

SubQuery 是單個子指令,任何的變更都會回傳一份複製子指令來避免多個 Goroutine 編輯同個子指令指標建構體。

func (*SubQuery) Get

func (s *SubQuery) Get(columns ...string) (subQuery *SubQuery)

Get 會取得多列的資料結果,傳入的參數為欲取得的欄位名稱,不傳入參數表示取得所有欄位。

func (*SubQuery) GroupBy

func (s *SubQuery) GroupBy(columns ...string) (subQuery *SubQuery)

GroupBy 會在執行 SQL 指令時依照特定的欄位來做執行區分。

func (*SubQuery) Having

func (s *SubQuery) Having(args ...interface{}) (subQuery *SubQuery)

Having 會增加一個 `HAVING AND` 條件式。

func (*SubQuery) InnerJoin

func (s *SubQuery) InnerJoin(table interface{}, condition string) (subQuery *SubQuery)

InnerJoin 會內部插入一個資料表格。

func (*SubQuery) JoinOrWhere

func (s *SubQuery) JoinOrWhere(table interface{}, args ...interface{}) (subQuery *SubQuery)

JoinOrWhere 能夠建立一個基於 `WHERE OR` 的條件式給某個指定的插入資料表格。

func (*SubQuery) JoinWhere

func (s *SubQuery) JoinWhere(table interface{}, args ...interface{}) (subQuery *SubQuery)

JoinWhere 能夠建立一個基於 `WHERE AND` 的條件式給某個指定的插入資料表格。

func (*SubQuery) LeftJoin

func (s *SubQuery) LeftJoin(table interface{}, condition string) (subQuery *SubQuery)

LeftJoin 會向左插入一個資料表格。

func (*SubQuery) Limit

func (s *SubQuery) Limit(from int, count ...int) (subQuery *SubQuery)

Limit 能夠在 SQL 查詢指令中建立限制筆數的條件。

func (*SubQuery) NaturalJoin

func (s *SubQuery) NaturalJoin(table interface{}, condition string) (subQuery *SubQuery)

NaturalJoin 會自然插入一個資料表格。

func (*SubQuery) OrHaving

func (s *SubQuery) OrHaving(args ...interface{}) (subQuery *SubQuery)

OrHaving 會增加一個 `HAVING OR` 條件式。

func (*SubQuery) OrWhere

func (s *SubQuery) OrWhere(args ...interface{}) (subQuery *SubQuery)

OrWhere 會增加一個 `WHERE OR` 條件式。

func (*SubQuery) OrderBy

func (s *SubQuery) OrderBy(column string, args ...interface{}) (subQuery *SubQuery)

OrderBy 會依照指定的欄位來替結果做出排序(例如:`DESC`、`ASC`)。

func (*SubQuery) Paginate

func (s *SubQuery) Paginate(pageCount int, columns ...string) (subQuery *SubQuery)

Paginate 基本上和 `Get` 取得函式無異,但此函式能夠自動依照分頁數來推算該從哪裡繼續取得資料。 使用時須先確定是否有指定 `PageLimit`(預設為:20),這樣才能限制一頁有多少筆資料。

func (*SubQuery) RawQuery

func (s *SubQuery) RawQuery(query string, values ...interface{}) (subQuery *SubQuery)

RawQuery 會接收傳入的變數來執行傳入的 SQL 執行語句,變數可以在語句中以 `?`(Prepared Statements)使用來避免 SQL 注入攻擊。 這會將多筆資料映射到本地的建構體切片、陣列上。

func (*SubQuery) RightJoin

func (s *SubQuery) RightJoin(table interface{}, condition string) (subQuery *SubQuery)

RightJoin 會向右插入一個資料表格。

func (*SubQuery) Table

func (s *SubQuery) Table(tableName ...string) (subQuery *SubQuery)

Table 能夠指定資料表格的名稱。

func (*SubQuery) Where

func (s *SubQuery) Where(args ...interface{}) (subQuery *SubQuery)

Where 會增加一個 `WHERE AND` 條件式。

type Timestamp

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

Timestamp 是一個資料庫的時間戳輔助函式。

func (Timestamp) IsDate

func (t Timestamp) IsDate(date string) Timestamp

IsDate 會確保欄位的時間戳是某個指定的年月日期。

func (Timestamp) IsDay

func (t Timestamp) IsDay(day int) Timestamp

IsDay 會確保欄位的時間戳是某個指定的天數。

func (Timestamp) IsHour

func (t Timestamp) IsHour(hour int) Timestamp

IsHour 會確保欄位的時間戳是某個指定的時數。

func (Timestamp) IsMinute

func (t Timestamp) IsMinute(minute int) Timestamp

IsMinute 會確保欄位的時間戳是某個指定的分鐘。

func (Timestamp) IsMonth

func (t Timestamp) IsMonth(month interface{}) Timestamp

IsMonth 會確保欄位的時間戳是某個指定的月份, 可以傳入字串的 `January`、`Jan` 或正整數的 `1` 作為月份。

func (Timestamp) IsSecond

func (t Timestamp) IsSecond(second int) Timestamp

IsSecond 會確保欄位的時間戳是某個指定的秒數。

func (Timestamp) IsWeekday

func (t Timestamp) IsWeekday(weekday interface{}) Timestamp

IsWeekday 會確保欄位的時間戳是某個指定的星期。 可以傳入字串的 `Monday`、`Mon` 或正整數的 `1` 作為星期。

func (Timestamp) IsYear

func (t Timestamp) IsYear(year int) Timestamp

IsYear 會確保欄位的時間戳是某個指定的年份。

type Trace

type Trace struct {
	Query    string
	Duration time.Duration
	Stacks   []map[string]interface{}
	Error    error
}

Trace 是個已執行的 SQL 指令蹤跡、堆疊資料。

Jump to

Keyboard shortcuts

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