mirror of
https://github.com/hanzoai/sqlbuilder.git
synced 2026-10-01 00:37:42 +00:00
update doc and provide more samples
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
[](https://travis-ci.org/huandu/go-sqlbuilder)
|
||||
[](https://godoc.org/github.com/huandu/go-sqlbuilder)
|
||||
|
||||
Package `sqlbuilder` provides a set of flexible and powerful SQL string builders. The only goal of this package is to build SQL string with arguments which can be used in `DB#Query` defined in package `database/sql`.
|
||||
Package `sqlbuilder` provides a set of flexible and powerful SQL string builders. The only goal of this package is to build SQL string with arguments which can be used in `DB#Query` or `DB#Exec` defined in package `database/sql`.
|
||||
|
||||
## Install ##
|
||||
|
||||
@@ -75,8 +75,8 @@ var userStruct = NewStruct(new(User))
|
||||
|
||||
func ExampleStruct() {
|
||||
// Prepare SELECT query.
|
||||
// SELECT id, name, status FROM user WHERE id = 1234
|
||||
sb := userStruct.Select("user")
|
||||
// SELECT id, name, status FROM user WHERE id = 1234 LIMIT 1
|
||||
sb := userStruct.SelectFrom("user")
|
||||
sb.Where(sb.E("id", 1234))
|
||||
|
||||
// Execute the query.
|
||||
@@ -190,16 +190,16 @@ fmt.Println(args)
|
||||
// [1 2]
|
||||
```
|
||||
|
||||
### Using a special syntax to build SQL ###
|
||||
### Using special syntax to build SQL ###
|
||||
|
||||
Package `sqlbuilder` defines a special syntax to represent an uncompiled SQL internally. If we want to take advantage of the syntax to build customized tools, we can use `Build` to compile it with arguments.
|
||||
Package `sqlbuilder` defines special syntax to represent an uncompiled SQL internally. If we want to take advantage of the syntax to build customized tools, we can use `Build` to compile it with arguments.
|
||||
|
||||
The format string uses a special syntax to represent arguments.
|
||||
The format string uses special syntax to represent arguments.
|
||||
|
||||
* `$?` uses successive arguments passed in the call. It works similar as `%v` in `fmt.Sprintf`.
|
||||
* `$0` `$1` ... `$n` uses nth-argument passed in the call. Next `$?` will use arguments n+1.
|
||||
* `${name}` uses a named argument created by `Named` with `name`.
|
||||
* `$$` represents a `"$"` string.
|
||||
* `$?` refers successive arguments passed in the call. It works similar as `%v` in `fmt.Sprintf`.
|
||||
* `$0` `$1` ... `$n` refers nth-argument passed in the call. Next `$?` will use arguments n+1.
|
||||
* `${name}` refers a named argument created by `Named` with `name`.
|
||||
* `$$` is a `"$"` string.
|
||||
|
||||
```go
|
||||
sb := sqlbuilder.NewSelectBuilder()
|
||||
|
||||
@@ -63,10 +63,10 @@ func (args *Args) add(arg interface{}) int {
|
||||
//
|
||||
// The format string uses a special syntax to represent arguments.
|
||||
//
|
||||
// $? uses successive arguments passed in the call. It works similar as `%v` in `fmt.Sprintf`.
|
||||
// $0 $1 ... $n uses nth-argument passed in the call. Next $? will use arguments n+1.
|
||||
// ${name} uses a named argument created by `Named` with `name`.
|
||||
// $$ represents a "$" string.
|
||||
// $? refers successive arguments passed in the call. It works similar as `%v` in `fmt.Sprintf`.
|
||||
// $0 $1 ... $n refers nth-argument passed in the call. Next $? will use arguments n+1.
|
||||
// ${name} refers a named argument created by `Named` with `name`.
|
||||
// $$ is a "$" string.
|
||||
func (args *Args) Compile(format string) (query string, values []interface{}) {
|
||||
buf := &bytes.Buffer{}
|
||||
idx := strings.IndexRune(format, '$')
|
||||
|
||||
@@ -94,21 +94,21 @@ func (s *Struct) parse(t reflect.Type) {
|
||||
}
|
||||
}
|
||||
|
||||
// Select creates a new `SelectBuilder` with table name.
|
||||
// SelectFrom creates a new `SelectBuilder` with table name.
|
||||
// By default, all exported fields of the s are listed as columns in SELECT
|
||||
// and LIMIT is set to 1.
|
||||
//
|
||||
// Caller is responsible to set WHERE condition to find right record.
|
||||
func (s *Struct) Select(table string) *SelectBuilder {
|
||||
return s.SelectForTag(table, "")
|
||||
func (s *Struct) SelectFrom(table string) *SelectBuilder {
|
||||
return s.SelectFromForTag(table, "")
|
||||
}
|
||||
|
||||
// SelectForTag creates a new `SelectBuilder` with table name for a specified tag.
|
||||
// SelectFromForTag creates a new `SelectBuilder` with table name for a specified tag.
|
||||
// By default, all fields of the s tagged with tag are listed as columns in SELECT
|
||||
// and LIMIT is set to 1.
|
||||
//
|
||||
// Caller is responsible to set WHERE condition to find right record.
|
||||
func (s *Struct) SelectForTag(table string, tag string) *SelectBuilder {
|
||||
func (s *Struct) SelectFromForTag(table string, tag string) *SelectBuilder {
|
||||
sb := NewSelectBuilder()
|
||||
sb.From(table)
|
||||
sb.Limit(1)
|
||||
|
||||
+107
-6
@@ -18,8 +18,8 @@ type structUserForTest struct {
|
||||
|
||||
var userForTest = NewStruct(new(structUserForTest))
|
||||
|
||||
func TestStructSelect(t *testing.T) {
|
||||
sb := userForTest.Select("user")
|
||||
func TestStructSelectFrom(t *testing.T) {
|
||||
sb := userForTest.SelectFrom("user")
|
||||
sql, args := sb.Build()
|
||||
|
||||
if expected := "SELECT id, Name, status, created_at FROM user LIMIT 1"; expected != sql {
|
||||
@@ -31,8 +31,8 @@ func TestStructSelect(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructSelectForTag(t *testing.T) {
|
||||
sb := userForTest.SelectForTag("user", "important")
|
||||
func TestStructSelectFromForTag(t *testing.T) {
|
||||
sb := userForTest.SelectFromForTag("user", "important")
|
||||
sql, args := sb.Build()
|
||||
|
||||
if expected := "SELECT id, Name, status FROM user LIMIT 1"; expected != sql {
|
||||
@@ -189,6 +189,19 @@ type User struct {
|
||||
Status int `db:"status"`
|
||||
}
|
||||
|
||||
type Order struct {
|
||||
ID int64 `db:"id" fieldtag:"new"`
|
||||
State State `db:"state" fieldtag:"new,paid,done"`
|
||||
SkuID int64 `db:"sku_id" fieldtag:"new"`
|
||||
UserID int64 `db:"user_id" fieldtag:"new"`
|
||||
Price int64 `db:"price" fieldtag:"new,update"`
|
||||
Discount int64 `db:"discount" fieldtag:"new,update"`
|
||||
Description string `db:"description" fieldtag:"new,update"`
|
||||
CreatedAt int64 `db:"created_at" fieldtag:"new"`
|
||||
ModifiedAt int64 `db:"modified_at" fieldtag:"new,update,paid,done"`
|
||||
}
|
||||
|
||||
type State int
|
||||
type testDB int
|
||||
type testRows int
|
||||
|
||||
@@ -210,9 +223,16 @@ func (rows testRows) Scan(dest ...interface{}) error {
|
||||
}
|
||||
|
||||
var userStruct = NewStruct(new(User))
|
||||
var orderStruct = NewStruct(new(Order))
|
||||
var db testDB
|
||||
|
||||
func ExampleStruct_buildSELECTAndUseItAsORM() {
|
||||
const (
|
||||
OrderStateInvalid State = iota
|
||||
OrderStateCreated
|
||||
OrderStatePaid
|
||||
)
|
||||
|
||||
func ExampleStruct_useStructAsORM() {
|
||||
// Suppose we defined following type and global variable.
|
||||
//
|
||||
// type User struct {
|
||||
@@ -224,7 +244,7 @@ func ExampleStruct_buildSELECTAndUseItAsORM() {
|
||||
// var userStruct = NewStruct(new(User))
|
||||
|
||||
// Prepare SELECT query.
|
||||
sb := userStruct.Select("user")
|
||||
sb := userStruct.SelectFrom("user")
|
||||
sb.Where(sb.E("id", 1234))
|
||||
|
||||
// Execute the query.
|
||||
@@ -246,6 +266,87 @@ func ExampleStruct_buildSELECTAndUseItAsORM() {
|
||||
// sqlbuilder.User{ID:1234, Name:"huandu", Status:1}
|
||||
}
|
||||
|
||||
func ExampleStruct_useTag() {
|
||||
// Suppose we defined following type and global variable.
|
||||
//
|
||||
// type Order struct {
|
||||
// ID int64 `db:"id" fieldtag:"update,paid"`
|
||||
// State int `db:"state" fieldtag:"paid"`
|
||||
// SkuID int64 `db:"sku_id"`
|
||||
// UserID int64 `db:"user_id"`
|
||||
// Price int64 `db:"price" fieldtag:"update"`
|
||||
// Discount int64 `db:"discount" fieldtag:"update"`
|
||||
// Description string `db:"description" fieldtag:"update"`
|
||||
// CreatedAt int64 `db:"created_at"`
|
||||
// ModifiedAt int64 `db:"modified_at" fieldtag:"update,paid"`
|
||||
// }
|
||||
//
|
||||
// var orderStruct = NewStruct(new(Order))
|
||||
|
||||
createOrder := func(table string) {
|
||||
order := &Order{
|
||||
ID: 1234,
|
||||
State: OrderStateCreated,
|
||||
SkuID: 5678,
|
||||
UserID: 7527,
|
||||
Price: 1000,
|
||||
Discount: 0,
|
||||
Description: "Best goods",
|
||||
CreatedAt: 1234567890,
|
||||
ModifiedAt: 1234567890,
|
||||
}
|
||||
b := orderStruct.InsertInto(table, &order)
|
||||
sql, args := b.Build()
|
||||
db.Exec(sql, args)
|
||||
}
|
||||
updatePrice := func(table string) {
|
||||
tag := "update"
|
||||
|
||||
var order Order
|
||||
sql, args := orderStruct.SelectFromForTag(table, tag).Where("id = 1234").Build()
|
||||
rows, _ := db.Query(sql, args...)
|
||||
rows.Scan(orderStruct.AddrForTag(tag, &order)...)
|
||||
|
||||
// Discount for this user.
|
||||
// Use tag "update" to update necessary columns only.
|
||||
order.Discount += 100
|
||||
b := orderStruct.UpdateForTag(table, tag, &order)
|
||||
b.Where(b.E("id", order.ID))
|
||||
sql, args = b.Build()
|
||||
db.Exec(sql, args...)
|
||||
}
|
||||
updateState := func(table string) {
|
||||
tag := "paid"
|
||||
|
||||
var order Order
|
||||
sql, args := orderStruct.SelectFromForTag(table, tag).Where("id = 1234").Build()
|
||||
rows, _ := db.Query(sql, args...)
|
||||
rows.Scan(orderStruct.AddrForTag(tag, &order)...)
|
||||
|
||||
// Update state to paid when user has paid for the order.
|
||||
// Use tag "paid" to update necessary columns only.
|
||||
if order.State != OrderStateCreated {
|
||||
// Report state error here.
|
||||
return
|
||||
}
|
||||
|
||||
order.State = OrderStatePaid
|
||||
b := orderStruct.UpdateForTag(table, tag, &order)
|
||||
b.Where(b.E("id", order.ID))
|
||||
sql, args = b.Build()
|
||||
db.Exec(sql, args...)
|
||||
}
|
||||
|
||||
table := "order"
|
||||
createOrder(table)
|
||||
updatePrice(table)
|
||||
updateState(table)
|
||||
|
||||
fmt.Println("done")
|
||||
// Output:
|
||||
// done
|
||||
}
|
||||
|
||||
func ExampleStruct_buildUPDATE() {
|
||||
// Suppose we defined following type and global variable.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user