refs #78 add new fieldas tag to set AS name for SELECT

This commit is contained in:
Huan Du
2022-07-21 22:14:43 +08:00
parent 3dc5cbacd2
commit 72a87cb0b7
4 changed files with 36 additions and 1 deletions
+1
View File
@@ -136,6 +136,7 @@ type ATable struct {
Field2 int `db:"field2"` // Use "db" in field tag to set column name used in SQL.
Field3 int64 `db:"field3" fieldtag:"foo,bar"` // Set fieldtag to a field. We can use methods like `Struct#SelectForTag` to use it.
Field4 int64 `db:"field4" fieldtag:"foo"` // If we use `s.SelectForTag(table, "foo")`, columnes of SELECT are field3 and field4.
Field5As string `db:"field5" fieldas:"FIELD5"` // Use "fieldas" in field tag to set AS name used in SELECT.
Ignored int32 `db:"-"` // If we set field name as "-", Struct will ignore it.
unexported int // Unexported field is not visible to Struct.
Quoted string `db:"quoted" fieldopt:"withquote"` // Add quote to the field using back quote or double quote. See `Flavor#Quote`.
+10 -1
View File
@@ -22,6 +22,9 @@ var (
// FieldOpt is the options for a struct field.
// As db column can contain "," in theory, field options should be provided in a separated tag.
FieldOpt = "fieldopt"
// FieldAs is the AS name for a struct field.
FieldAs = "fieldas"
)
const (
@@ -117,7 +120,13 @@ func (s *Struct) SelectFromForTag(table string, tag string) *SelectBuilder {
for _, field := range fields {
buf.WriteString(table)
buf.WriteRune('.')
buf.WriteString(field)
if fieldas, exists := sf.fieldAs[field]; exists {
buf.WriteString(sb.As(field, fieldas))
} else {
buf.WriteString(field)
}
cols = append(cols, buf.String())
buf.Reset()
}
+16
View File
@@ -776,6 +776,22 @@ func TestStructFieldMapper(t *testing.T) {
a.Equal(sql, "SELECT t.`FieldName1`, t.set_by_tag, t.field_name1, t.EmbeddedField2, t.EmbeddedAndEmbeddedField1 FROM t")
}
type structWithAs struct {
T1 string `db:"t1" fieldas:"f1"`
T2 string `db:"t2" fieldas:""` // Empty fieldas is the same as the tag is not set.
T3 string `fieldas:"f3"` // AS works without db tag.
T4 string `db:"t4" fieldas:"f3"` // fieldas tag can duplicate.
}
func TestStructFieldAs(t *testing.T) {
a := assert.New(t)
s := NewStruct(new(structWithAs))
sb := s.SelectFrom("t")
b := Build(`COPY ($?) TO '/path/to/file.csv' (FORMAT CSV, HEADER)`, sb)
sql, _ := b.Build()
a.Equal(sql, `COPY (SELECT t.t1 AS f1, t.t2, t.T3 AS f3, t.t4 AS f3 FROM t) TO '/path/to/file.csv' (FORMAT CSV, HEADER)`)
}
func SomeOtherMapper(string) string {
return ""
}
+9
View File
@@ -7,6 +7,7 @@ import (
type structFields struct {
fieldAlias map[string]string
fieldAs map[string]string
taggedFields map[string][]string
quotedFields map[string]struct{}
omitEmptyFields map[string]omitEmptyTagMap
@@ -26,6 +27,7 @@ func makeFieldsParser(t reflect.Type, mapper FieldMapperFunc, useDefault bool) s
var once sync.Once
sf := &structFields{
fieldAlias: map[string]string{},
fieldAs: map[string]string{},
taggedFields: map[string][]string{},
quotedFields: map[string]struct{}{},
omitEmptyFields: map[string]omitEmptyTagMap{},
@@ -118,6 +120,13 @@ func (sf *structFields) parse(t reflect.Type, mapper FieldMapperFunc, prefix str
sf.quotedFields[alias] = struct{}{}
}
}
// Parse FieldAs.
fieldas := field.Tag.Get(FieldAs)
if fieldas != "" {
sf.fieldAs[alias] = fieldas
}
}
for _, field := range anonymous {