diff --git a/core/stores/sqlx/orm.go b/core/stores/sqlx/orm.go index 678847e12..d13e8eefe 100644 --- a/core/stores/sqlx/orm.go +++ b/core/stores/sqlx/orm.go @@ -279,6 +279,11 @@ func unwrapFields(v reflect.Value) []reflect.Value { if child.Kind() == reflect.Struct && childType.Anonymous { fields = append(fields, unwrapFields(child)...) } else { + key := parseTagName(childType) + if key == "-" { + continue + } + fields = append(fields, child) } } diff --git a/core/stores/sqlx/orm_test.go b/core/stores/sqlx/orm_test.go index fcd0f2e8e..55d1aa16c 100644 --- a/core/stores/sqlx/orm_test.go +++ b/core/stores/sqlx/orm_test.go @@ -370,6 +370,39 @@ func TestUnmarshalRowStructWithTags(t *testing.T) { }) } +func TestUnmarshalRowStructWithTagsIgnoreFields(t *testing.T) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + value := new(struct { + Age int `db:"age"` + Name string + Ignore bool + }) + + rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("liao,5") + mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) + + assert.ErrorIs(t, query(context.Background(), db, func(rows *sql.Rows) error { + return unmarshalRow(value, rows, true) + }, "select name, age from users where user=?", "anyone"), ErrNotMatchDestination) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + value := new(struct { + Age int `db:"age"` + Name string + Ignore bool `db:"-"` + }) + + rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("liao,5") + mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) + + assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { + return unmarshalRow(value, rows, true) + }, "select name, age from users where user=?", "anyone")) + assert.Equal(t, 5, value.Age) + }) +} + func TestUnmarshalRowStructWithTagsWrongColumns(t *testing.T) { value := new(struct { Age *int `db:"age"` @@ -999,6 +1032,58 @@ func TestUnmarshalRowsStructWithTags(t *testing.T) { }) } +func TestUnmarshalRowsStructWithTagsIgnoreFields(t *testing.T) { + expect := []struct { + Name string + Age int64 + Ignore bool + }{ + { + Name: "first", + Age: 2, + Ignore: false, + }, + { + Name: "second", + Age: 3, + Ignore: false, + }, + } + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + var value []struct { + Age int64 `db:"age"` + Name string `db:"name"` + Ignore bool + } + + rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("first,2\nsecond,3") + mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) + assert.ErrorIs(t, query(context.Background(), db, func(rows *sql.Rows) error { + return unmarshalRows(&value, rows, true) + }, "select name, age from users where user=?", "anyone"), ErrNotMatchDestination) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + var value []struct { + Age int64 `db:"age"` + Name string `db:"name"` + Ignore bool `db:"-"` + } + + rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("first,2\nsecond,3") + mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) + assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { + return unmarshalRows(&value, rows, true) + }, "select name, age from users where user=?", "anyone")) + + for i, each := range expect { + assert.Equal(t, each.Name, value[i].Name) + assert.Equal(t, each.Age, value[i].Age) + } + }) +} + func TestUnmarshalRowsStructAndEmbeddedAnonymousStructWithTags(t *testing.T) { type Embed struct { Value int64 `db:"value"`