Documentation ¶
Overview ¶
Package sqlstruct provides some convenience functions for using structs with the Go standard library's database/sql package.
The package matches struct field names to SQL query column names. A field can also specify a matching column with "sql" tag, if it's different from field name. Unexported fields or fields marked with `sql:"-"` are ignored, just like with "encoding/json" package.
For example:
type T struct { F1 string F2 string `sql:"field2"` F3 string `sql:"-"` } rows, err := db.Query(fmt.Sprintf("SELECT %s FROM tablename", sqlstruct.Columns(T{}))) ... for rows.Next() { var t T err = sqlstruct.Scan(&t, rows) ... } err = rows.Err() // get any errors encountered during iteration
Aliased tables in a SQL statement may be scanned into a specific structure identified by the same alias, using the ColumnsAliased and ScanAliased functions:
type User struct { Id int `sql:"id"` Username string `sql:"username"` Email string `sql:"address"` Name string `sql:"name"` HomeAddress *Address `sql:"-"` } type Address struct { Id int `sql:"id"` City string `sql:"city"` Street string `sql:"address"` } ... var user User var address Address sql := ` SELECT %s, %s FROM users AS u INNER JOIN address AS a ON a.id = u.address_id WHERE u.username = ? ` sql = fmt.Sprintf(sql, sqlstruct.ColumnsAliased(*user, "u"), sqlstruct.ColumnsAliased(*address, "a")) rows, err := db.Query(sql, "gedi") if err != nil { log.Fatal(err) } defer rows.Close() if rows.Next() { err = sqlstruct.ScanAliased(&user, rows, "u") if err != nil { log.Fatal(err) } err = sqlstruct.ScanAliased(&address, rows, "a") if err != nil { log.Fatal(err) } user.HomeAddress = address } fmt.Printf("%+v", *user) // output: "{Id:1 Username:gedi Email:gediminas.morkevicius@gmail.com Name:Gedas HomeAddress:0xc21001f570}" fmt.Printf("%+v", *user.HomeAddress) // output: "{Id:2 City:Vilnius Street:Plento 34}"
Index ¶
- Variables
- func Columns[T any]() string
- func ColumnsAliased[T any](alias string) string
- func Query[T any](query string, args ...any) (slice []T, err error)
- func QueryInts(query string, args ...any) (results []int, err error)
- func QueryRow[T any](query string, args ...any) (stru T, err error)
- func Scan[T any](dest *T, rows Rows) error
- func ScanAliased[T any](dest *T, rows Rows, alias string) error
- func SetDatabase(sqldb *sql.DB)
- func SliceFromRows[T any](rows *sql.Rows) (slice []T, err error)
- func ToSnakeCase(src string) string
- type Rows
- type Scanner
Constants ¶
This section is empty.
Variables ¶
var ( // NameMapper is the function used to convert struct fields which do not have sql tags // into database column names. // // The default mapper converts field names to lower case. If instead you would prefer // field names converted to snake case, simply assign sqlstruct.ToSnakeCase to the variable: // // sqlstruct.NameMapper = sqlstruct.ToSnakeCase // // Alternatively for a custom mapping, any func(string) string can be used instead. NameMapper = strings.ToLower // TagName is the name of the tag to use on struct fields TagName = "sql" QueryReplace = "*" )
Functions ¶
func Columns ¶
Columns returns a string containing a sorted, comma-separated list of column names as defined by the type s. s must be a struct that has exported fields tagged with the "sql" tag.
func ColumnsAliased ¶
ColumnsAliased works like Columns except it prefixes the resulting column name with the given alias.
For each field in the given struct it will generate a statement like:
alias.field AS alias_field
It is intended to be used in conjunction with the ScanAliased function.
func Query ¶
Query executes the given query using the global database handle and returns the resulting objects in a slice. SetDatabase must be called before using this function. The query should use the QueryReplace (* by default) string to indicate where the columns from the struct type T should be inserted.
For example for the following struct:
type User struct { ID int Name string }
and the following query
SELECT * FROM users WHERE id = ?
the query sent to the database will be
SELECT id, name FROM users WHERE id = ?
and a list of User objects will be returned.
func QueryRow ¶
QueryRow works similar to Query except it returns only the first row from the result set. SetDatabase must be called before using this function. The query should use the QueryReplace (* by default) string to indicate where the columns from the struct type T should be inserted.
func Scan ¶
Scan scans the next row from rows in to a struct pointed to by dest. The struct type should have exported fields tagged with the "sql" tag. Columns from row which are not mapped to any struct fields are ignored. Struct fields which have no matching column in the result set are left unchanged.
func ScanAliased ¶
ScanAliased works like scan, except that it expects the results in the query to be prefixed by the given alias.
For example, if scanning to a field named "name" with an alias of "user" it will expect to find the result in a column named "user_name".
See ColumnAliased for a convenient way to generate these queries.
func SetDatabase ¶
SetDatabase sets the global database handle to be used by the Query function.
func SliceFromRows ¶
SliceFromRows returns a slice of structs from the given rows by calling Scan on each row.
func ToSnakeCase ¶
ToSnakeCase converts a string to snake case, words separated with underscores. It's intended to be used with NameMapper to map struct field names to snake case database fields.