mirror of
https://github.com/kataras/iris.git
synced 2025-12-24 13:27:03 +00:00
add a new x/sqlx sub-package and example
This commit is contained in:
92
x/sqlx/struct_row.go
Normal file
92
x/sqlx/struct_row.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package sqlx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris/v12/x/reflex"
|
||||
)
|
||||
|
||||
// DefaultTag is the default struct field tag.
|
||||
var DefaultTag = "db"
|
||||
|
||||
type ColumnNameFunc = func(string) string
|
||||
|
||||
func convertStructToColumns(typ reflect.Type, nameFunc ColumnNameFunc) (map[string]*Column, error) {
|
||||
if kind := typ.Kind(); kind != reflect.Struct {
|
||||
return nil, fmt.Errorf("convert struct: invalid type: expected a struct value but got: %q", kind.String())
|
||||
}
|
||||
|
||||
// Retrieve only fields valid for database.
|
||||
fields := reflex.LookupFields(typ, "")
|
||||
|
||||
columns := make(map[string]*Column, len(fields))
|
||||
for i, field := range fields {
|
||||
column, ok, err := convertStructFieldToColumn(field, DefaultTag, nameFunc)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("convert struct: field name: %q: %w", field.Name, err)
|
||||
}
|
||||
|
||||
column.Index = i
|
||||
columns[column.Name] = column
|
||||
}
|
||||
|
||||
return columns, nil
|
||||
}
|
||||
|
||||
func convertStructFieldToColumn(field reflect.StructField, optionalTag string, nameFunc ColumnNameFunc) (*Column, bool, error) {
|
||||
c := &Column{
|
||||
Name: nameFunc(field.Name),
|
||||
FieldIndex: field.Index,
|
||||
}
|
||||
|
||||
fieldTag, ok := field.Tag.Lookup(optionalTag)
|
||||
if ok {
|
||||
if fieldTag == "-" {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
if err := parseOptions(fieldTag, c); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
return c, true, nil
|
||||
}
|
||||
|
||||
func parseOptions(fieldTag string, c *Column) error {
|
||||
options := strings.Split(fieldTag, ",")
|
||||
for _, opt := range options {
|
||||
if opt == "" {
|
||||
continue // skip empty.
|
||||
}
|
||||
|
||||
var key, value string
|
||||
|
||||
kv := strings.Split(opt, "=") // When more options come to play.
|
||||
switch len(kv) {
|
||||
case 2:
|
||||
key = kv[0]
|
||||
value = kv[1]
|
||||
case 1:
|
||||
c.Name = kv[0]
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("option: %s: expected key value separated by '='", opt)
|
||||
}
|
||||
|
||||
switch key {
|
||||
case "name":
|
||||
c.Name = value
|
||||
default:
|
||||
return fmt.Errorf("unexpected tag option: %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user