Skip to content

Commit

Permalink
Merge pull request #79 from huandu/feature-fieldas
Browse files Browse the repository at this point in the history
Add new `fieldas` tag to set AS name for SELECT
  • Loading branch information
huandu authored Jul 24, 2022
2 parents 20e19b9 + ebd3252 commit a283436
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Field5 string `db:"field5" fieldas:"f5_alias"` // Use "fieldas" in field tag to set a column alias (AS) 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`.
Expand Down
11 changes: 10 additions & 1 deletion struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 column alias (AS) for a struct field.
FieldAs = "fieldas"
)

const (
Expand Down Expand Up @@ -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()
}
Expand Down
16 changes: 16 additions & 0 deletions struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 ""
}
Expand Down
9 changes: 9 additions & 0 deletions structfields.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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{},
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit a283436

Please sign in to comment.