Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update documentation on named bind parameters. #7

Merged
merged 1 commit into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,9 @@ s, err := dbmap.SelectStr("select name from foo where blah=?", blahVal)

#### Named bind parameters

You may use a map or struct to bind parameters by name. This is currently
only supported in SELECT queries.
You may use a map or struct to bind parameters by name. This is supported in
the Exec and Select* functions on DbMap and Transaction. It is not supported by
Prepare, Query, or QueryRow.

```go
_, err := dbm.Select(&dest, "select * from Foo where name = :name and age = :age", map[string]interface{}{
Expand Down
48 changes: 1 addition & 47 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,53 +39,7 @@ type DbMap struct {

// ExpandSlices when enabled will convert slice arguments in mappers into flat
// values. It will modify the query, adding more placeholders, and the mapper,
// adding each item of the slice as a new unique entry in the mapper. For
// example, given the scenario bellow:
//
// dbmap.Select(&output, "SELECT 1 FROM example WHERE id IN (:IDs)", map[string]interface{}{
// "IDs": []int64{1, 2, 3},
// })
//
// The executed query would be:
//
// SELECT 1 FROM example WHERE id IN (:IDs0,:IDs1,:IDs2)
//
// With the mapper:
//
// map[string]interface{}{
// "IDs": []int64{1, 2, 3},
// "IDs0": int64(1),
// "IDs1": int64(2),
// "IDs2": int64(3),
// }
//
// It is also flexible for custom slice types. The value just need to
// implement stringer or numberer interfaces.
//
// type CustomValue string
//
// const (
// CustomValueHey CustomValue = "hey"
// CustomValueOh CustomValue = "oh"
// )
//
// type CustomValues []CustomValue
//
// func (c CustomValues) ToStringSlice() []string {
// values := make([]string, len(c))
// for i := range c {
// values[i] = string(c[i])
// }
// return values
// }
//
// func query() {
// // ...
// result, err := dbmap.Select(&output, "SELECT 1 FROM example WHERE value IN (:Values)", map[string]interface{}{
// "Values": CustomValues([]CustomValue{CustomValueHey}),
// })
// // ...
// }
// adding each item of the slice as a new unique entry in the mapper.
ExpandSliceArgs bool

tables []*TableMap
Expand Down
78 changes: 77 additions & 1 deletion doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,82 @@
// SQL databases. It uses the database/sql package, and should work with any
// compliant database/sql driver.
//
// Source code and project home:
// Source code, additional documentation, and examples:
// https://github.com/letsencrypt/borp
//
// # Query Parameters
//
// Borp's Exec, Select*, Query, and QueryRow methods accept placeholder
// parameters in the query, to be filled from the args parameters to these
// functions. Borp supports some additional styles for placeholder parameters:
//
// # Named Bind Parameters
//
// For the Exec and Select* methods on DbMap and Transaction, Borp supports
// named bind parameters. To use named bind parameters, instead of a list of
// parameters, pass a single `map[string]interface{}` to these functions. And
// instead of using ? in the query, use placeholder parameters of the form :word.
// Before running the query, Borp will bind each named placeholder parameter to the
// corresponding value found by looking up "word" in the map.
//
// Example:
//
// _, err := dbm.Select(&dest, "select * from Foo where name = :name and age = :age",
// map[string]interface{}{
// "name": "Rob",
// "age": 31,
// })
//
// # Expanding Slices
//
// If you set the ExpandSlices field of DbMap to true, placeholders that bind to
// slices will be handled specially. Borp will modify the query, adding more
// placeholders to match the number of entries in the slice.
//
// For example, given the scenario bellow:
//
// dbmap.Select(&output, "SELECT 1 FROM example WHERE id IN (:IDs)", map[string]interface{}{
// "IDs": []int64{1, 2, 3},
// })
//
// The executed query would be:
//
// SELECT 1 FROM example WHERE id IN (:IDs0,:IDs1,:IDs2)
//
// With the mapper:
//
// map[string]interface{}{
// "IDs": []int64{1, 2, 3},
// "IDs0": int64(1),
// "IDs1": int64(2),
// "IDs2": int64(3),
// }
//
// It is also flexible for custom slice types. The value just need to
// implement stringer or numberer interfaces.
//
// type CustomValue string
//
// const (
// CustomValueHey CustomValue = "hey"
// CustomValueOh CustomValue = "oh"
// )
//
// type CustomValues []CustomValue
//
// func (c CustomValues) ToStringSlice() []string {
// values := make([]string, len(c))
// for i := range c {
// values[i] = string(c[i])
// }
// return values
// }
//
// func query() {
// // ...
// result, err := dbmap.Select(&output, "SELECT 1 FROM example WHERE value IN (:Values)", map[string]interface{}{
// "Values": CustomValues([]CustomValue{CustomValueHey}),
// })
// // ...
// }
package borp