Skip to content

Commit

Permalink
Update documentation on named bind parameters. (#7)
Browse files Browse the repository at this point in the history
I wasn't able to find documentation of these in the godoc, so I added
it. Also, the README had out-of-date information. It said named bind
parameters were only supported for Select, but they are also supported
for Exec since 2015 (04b2c71).

The documentation for ExpandSlices was embedded in the DbMap type, which
made it hard to read on godoc - the entire documentation was in one
large `pre` block. I moved it up to the package level docs.

Note: this is a recreation of go-gorp#421

Co-authored-by: Jacob Hoffman-Andrews <[email protected]>
  • Loading branch information
aarongable and jsha authored Jul 5, 2023
1 parent 7dd23fd commit a4dac79
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 50 deletions.
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

0 comments on commit a4dac79

Please sign in to comment.