Documentation
¶
Overview ¶
Package sqluct provides integration of sqlx and squirrel.v1 with Go structures.
Index ¶
- func Columns(columns ...string) func(o *Options)
- func OrderDesc(o *Options)
- func SkipZeroValues(o *Options)
- func TxFromContext(ctx context.Context) *sqlx.Tx
- func TxToContext(ctx context.Context, tx *sqlx.Tx) context.Context
- type Mapper
- func (sm *Mapper) Col(structPtr, fieldPtr interface{}) string
- func (sm *Mapper) ColumnsValues(v reflect.Value, options ...func(*Options)) ([]string, []interface{})
- func (sm *Mapper) FindColumnName(structPtr, fieldPtr interface{}) (string, error)
- func (sm *Mapper) Insert(q squirrel.InsertBuilder, val interface{}, options ...func(*Options)) squirrel.InsertBuilder
- func (sm *Mapper) Order(columns interface{}, options ...func(*Options)) stringdeprecated
- func (sm *Mapper) Select(q squirrel.SelectBuilder, columns interface{}, options ...func(*Options)) squirrel.SelectBuilder
- func (sm *Mapper) Update(q squirrel.UpdateBuilder, val interface{}, options ...func(*Options)) squirrel.UpdateBuilder
- func (sm *Mapper) WhereEq(conditions interface{}, options ...func(*Options)) squirrel.Eq
- type Options
- type Storage
- func (s *Storage) Col(structPtr, fieldPtr interface{}) string
- func (s *Storage) DeleteStmt(tableName string) squirrel.DeleteBuilder
- func (s *Storage) Exec(ctx context.Context, qb ToSQL) (res sql.Result, err error)
- func (s *Storage) InTx(ctx context.Context, fn func(context.Context) error) (err error)
- func (s *Storage) InsertStmt(tableName string, val interface{}, options ...func(*Options)) squirrel.InsertBuilder
- func (s *Storage) Query(ctx context.Context, qb ToSQL) (*sqlx.Rows, error)
- func (s *Storage) QueryBuilder() squirrel.StatementBuilderType
- func (s *Storage) Select(ctx context.Context, qb ToSQL, dest interface{}) (err error)
- func (s *Storage) SelectStmt(tableName string, columns interface{}, options ...func(*Options)) squirrel.SelectBuilder
- func (s *Storage) UpdateStmt(tableName string, val interface{}, options ...func(*Options)) squirrel.UpdateBuilder
- func (s *Storage) WhereEq(conditions interface{}, options ...func(*Options)) squirrel.Eq
- type StringStatement
- type ToSQL
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func OrderDesc ¶
func OrderDesc(o *Options)
OrderDesc instructs mapper to use DESC order in Product func.
func SkipZeroValues ¶
func SkipZeroValues(o *Options)
SkipZeroValues instructs mapper to ignore fields with zero values.
func TxFromContext ¶
TxFromContext gets transaction or nil from context.
Types ¶
type Mapper ¶
Mapper prepares select, insert and update statements.
func (*Mapper) Col ¶
Col will try to find column name and will panic on error.
Example ¶
package main
import (
"fmt"
"time"
"github.com/Masterminds/squirrel"
"github.com/bool64/sqluct"
)
func main() {
sm := sqluct.Mapper{}
type Order struct {
ID int `db:"order_id"`
CreatedAt time.Time `db:"created_at"`
}
o := Order{
ID: 123,
}
q := sm.
Select(squirrel.Select(), o).
From("orders").
Where(squirrel.Eq{
sm.Col(&o, &o.ID): o.ID, // Col returns "order_id" defined in field tag.
})
query, args, err := q.ToSql()
fmt.Println(query, args, err)
}
Output: SELECT order_id, created_at FROM orders WHERE order_id = ? [123] <nil>
func (*Mapper) ColumnsValues ¶ added in v0.1.1
func (sm *Mapper) ColumnsValues(v reflect.Value, options ...func(*Options)) ([]string, []interface{})
ColumnsValues extracts columns and values from provided struct value.
func (*Mapper) FindColumnName ¶
FindColumnName returns column name of a database entity field.
Entity field is defined by pointer to owner structure and pointer to field in that structure.
entity := MyEntity{}
name, found := sm.FindColumnName(&entity, &entity.UpdatedAt)
func (*Mapper) Insert ¶
func (sm *Mapper) Insert(q squirrel.InsertBuilder, val interface{}, options ...func(*Options)) squirrel.InsertBuilder
Insert adds struct value or slice of struct values to squirrel.InsertBuilder.
Example ¶
package main
import (
"fmt"
"github.com/Masterminds/squirrel"
"github.com/bool64/sqluct"
)
func main() {
sm := sqluct.Mapper{}
type Order struct {
ID int `db:"order_id"`
Amount int `db:"amount"`
UserID int `db:"user_id"`
}
o := Order{}
o.Amount = 100
o.UserID = 123
q := sm.Insert(squirrel.Insert("orders"), o, sqluct.SkipZeroValues)
query, args, err := q.ToSql()
fmt.Println(query, args, err)
}
Output: INSERT INTO orders (amount,user_id) VALUES (?,?) [100 123] <nil>
func (*Mapper) Select ¶
func (sm *Mapper) Select(q squirrel.SelectBuilder, columns interface{}, options ...func(*Options)) squirrel.SelectBuilder
Select maps struct field tags as columns to squirrel.SelectBuilder, slice of struct is also accepted.
Example ¶
package main
import (
"fmt"
"github.com/Masterminds/squirrel"
"github.com/bool64/sqluct"
)
func main() {
sm := sqluct.Mapper{}
type OrderData struct {
Amount int `db:"amount"`
UserID int `db:"user_id"`
}
type Order struct {
ID int `db:"order_id"`
OrderData
}
o := Order{}
o.ID = 321
q := sm.
Select(squirrel.Select(), o).
Where(squirrel.Eq{sm.Col(&o, &o.ID): o.ID})
query, args, err := q.ToSql()
fmt.Println(query, args, err)
}
Output: SELECT order_id, amount, user_id WHERE order_id = ? [321] <nil>
func (*Mapper) Update ¶
func (sm *Mapper) Update(q squirrel.UpdateBuilder, val interface{}, options ...func(*Options)) squirrel.UpdateBuilder
Update sets struct value to squirrel.UpdateBuilder.
Example ¶
package main
import (
"fmt"
"github.com/Masterminds/squirrel"
"github.com/bool64/sqluct"
)
func main() {
sm := sqluct.Mapper{}
type OrderData struct {
Amount int `db:"amount"`
UserID int `db:"user_id"`
}
type Order struct {
ID int `db:"order_id"`
OrderData
}
o := Order{}
o.ID = 321
o.Amount = 100
o.UserID = 123
q := sm.
Update(squirrel.Update("orders"), o.OrderData).
Where(squirrel.Eq{sm.Col(&o, &o.ID): o.ID})
query, args, err := q.ToSql()
fmt.Println(query, args, err)
}
Output: UPDATE orders SET amount = ?, user_id = ? WHERE order_id = ? [100 123 321] <nil>
func (*Mapper) WhereEq ¶
WhereEq maps struct values as conditions to squirrel.Eq.
Example ¶
package main
import (
"fmt"
"github.com/Masterminds/squirrel"
"github.com/bool64/sqluct"
)
func main() {
sm := sqluct.Mapper{}
type OrderData struct {
Amount int `db:"amount"`
UserID int `db:"user_id"`
}
type Order struct {
ID int `db:"order_id"`
OrderData
}
o := Order{}
o.Amount = 100
o.UserID = 123
q := sm.
Select(squirrel.Select(), o).
Where(sm.WhereEq(o.OrderData))
query, args, err := q.ToSql()
fmt.Println(query, args, err)
}
Output: SELECT order_id, amount, user_id WHERE amount = ? AND user_id = ? [100 123] <nil>
type Options ¶
type Options struct {
// SkipZeroValues instructs mapper to ignore fields with zero values.
SkipZeroValues bool
// Columns is used to control which columns from the structure should be used.
Columns []string
// OrderDesc instructs mapper to use DESC order in Product func.
OrderDesc bool
}
Options defines mapping parameters.
type Storage ¶
type Storage struct {
Mapper *Mapper
// Format is a placeholder format, default squirrel.Dollar.
// Other values are squirrel.Question, squirrel.AtP and squirrel.Colon.
Format squirrel.PlaceholderFormat
// OnError is called when error is encountered, could be useful for logging.
OnError func(ctx context.Context, err error)
// Trace wraps a call to database.
// It takes statement as arguments and returns
// instrumented context with callback to call after db call is finished.
Trace func(ctx context.Context, stmt string, args []interface{}) (newCtx context.Context, onFinish func(error))
// contains filtered or unexported fields
}
Storage creates and executes database statements.
func (*Storage) DeleteStmt ¶
func (s *Storage) DeleteStmt(tableName string) squirrel.DeleteBuilder
DeleteStmt makes a delete query builder.
func (*Storage) InTx ¶
InTx runs callback in a transaction.
If transaction already exists, it will reuse that. Otherwise it starts a new transaction and commit or rollback (in case of error) at the end.
Example ¶
package main
import (
"context"
"log"
"github.com/bool64/sqluct"
)
func main() {
var (
s sqluct.Storage
ctx context.Context
)
err := s.InTx(ctx, func(ctx context.Context) error {
return nil
})
if err != nil {
log.Fatal(err)
}
}
Example (Full) ¶
package main
import (
"context"
"log"
"time"
"github.com/Masterminds/squirrel"
"github.com/bool64/sqluct"
)
func main() {
var (
s sqluct.Storage
ctx context.Context
)
const tableName = "products"
type Product struct {
ID int `db:"id"`
Title string `db:"title"`
CreatedAt time.Time `db:"created_at"`
}
// INSERT INTO products (id, title, created_at) VALUES (1, 'Apples', <now>), (2, 'Oranges', <now>)
_, err := s.Exec(ctx, s.InsertStmt(tableName, []Product{
{
ID: 1,
Title: "Apples",
CreatedAt: time.Now(),
}, {
ID: 2,
Title: "Oranges",
CreatedAt: time.Now(),
},
}))
if err != nil {
log.Fatal(err)
}
// UPDATE products SET title = 'Bananas' WHERE id = 2
_, err = s.Exec(
ctx,
s.UpdateStmt(tableName, Product{Title: "Bananas"}, sqluct.SkipZeroValues).
Where(s.WhereEq(Product{ID: 2}, sqluct.SkipZeroValues)),
)
if err != nil {
log.Fatal(err)
}
var (
result []Product
row Product
)
// SELECT id, title, created_at FROM products WHERE id != 3 AND created_at <= <now>
err = s.Select(ctx,
s.SelectStmt(tableName, row).
Where(squirrel.NotEq(s.WhereEq(Product{ID: 3}, sqluct.SkipZeroValues))).
Where(squirrel.LtOrEq{s.Col(&row, &row.CreatedAt): time.Now()}),
&result,
)
if err != nil {
log.Fatal(err)
}
// DELETE FROM products WHERE id = 2
_, err = s.Exec(ctx, s.DeleteStmt(tableName).Where(Product{ID: 2}, sqluct.SkipZeroValues))
if err != nil {
log.Fatal(err)
}
}
func (*Storage) InsertStmt ¶
func (s *Storage) InsertStmt(tableName string, val interface{}, options ...func(*Options)) squirrel.InsertBuilder
InsertStmt makes an insert query builder.
Example ¶
package main
import (
"context"
"log"
"github.com/bool64/sqluct"
)
func main() {
var (
s sqluct.Storage
ctx context.Context
)
type MyEntity struct {
Name string `db:"name"`
Age int `db:"age"`
}
row := MyEntity{
Name: "Jane",
Age: 30,
}
qb := s.InsertStmt("my_table", row)
_, err := s.Exec(ctx, qb)
if err != nil {
log.Fatal(err)
}
}
func (*Storage) Query ¶
Query queries database and returns raw result.
Select is recommended to use instead of Query.
func (*Storage) QueryBuilder ¶
func (s *Storage) QueryBuilder() squirrel.StatementBuilderType
QueryBuilder returns query builder with placeholder format.
func (*Storage) Select ¶
Select queries statement of query builder and scans result into destination.
Destination can be a pointer to struct or slice, e.g. `*row` or `*[]row`.
Example (OneRow) ¶
package main
import (
"context"
"log"
"github.com/bool64/sqluct"
)
func main() {
var (
s sqluct.Storage
ctx context.Context
)
type MyEntity struct {
Name string `db:"name"`
Age int `db:"age"`
}
var row MyEntity
qb := s.SelectStmt("my_table", row)
err := s.Select(ctx, qb, &row)
if err != nil {
log.Fatal(err)
}
}
Example (Slice) ¶
package main
import (
"context"
"fmt"
"log"
"github.com/bool64/sqluct"
"github.com/jmoiron/sqlx"
)
func main() {
var (
db *sqlx.DB // Setup db connection.
ctx context.Context
)
s := sqluct.NewStorage(db)
// Define your entity as a struct with `db` field tags that correspond to column names in table.
type MyEntity struct {
Name string `db:"name"`
Age int `db:"age"`
}
// Create destination for query result.
rows := make([]MyEntity, 0, 100)
// Create SELECT statement from fields of entity.
qb := s.SelectStmt("my_table", MyEntity{}).
Where(s.WhereEq(MyEntity{
Name: "Jane",
}, sqluct.SkipZeroValues)) // Add WHERE condition built from fields of entity.
// Query statement would be
// SELECT name, age FROM my_table WHERE name = $1
// with argument 'Jane'.
err := s.Select(ctx, qb, &rows)
if err != nil {
log.Fatal(err)
}
for _, row := range rows {
fmt.Println(row)
}
}
func (*Storage) SelectStmt ¶
func (s *Storage) SelectStmt(tableName string, columns interface{}, options ...func(*Options)) squirrel.SelectBuilder
SelectStmt makes a select query builder.
func (*Storage) UpdateStmt ¶
func (s *Storage) UpdateStmt(tableName string, val interface{}, options ...func(*Options)) squirrel.UpdateBuilder
UpdateStmt makes an update query builder.
Example ¶
package main
import (
"context"
"log"
"github.com/bool64/sqluct"
)
func main() {
var (
s sqluct.Storage
ctx context.Context
)
type MyIdentity struct {
ID int `db:"id"`
}
type MyValue struct {
Name string `db:"name"`
Age int `db:"age"`
}
row := MyValue{
Name: "Jane",
Age: 30,
}
qb := s.UpdateStmt("my_table", row).
Where(s.Mapper.WhereEq(MyIdentity{ID: 123}))
_, err := s.Exec(ctx, qb)
if err != nil {
log.Fatal(err)
}
}
type StringStatement ¶
type StringStatement string
StringStatement is a plain string statement.
func (StringStatement) ToSql ¶
func (s StringStatement) ToSql() (string, []interface{}, error)
ToSql implements query builder result.