Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test case for omitted field #28

Merged
merged 2 commits into from
Mar 25, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add test case for omitted field
  • Loading branch information
twharmon committed Mar 25, 2022
commit 1760f6c0f06c9e3359cb8ba56b10d30bc5bdb8f2
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ db := gosql.New(sqliteDB)

// Define a struct that includes a primary key
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Email string
IsActive bool
}
Expand Down
17 changes: 10 additions & 7 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,17 @@ func (db *DB) register(typ reflect.Type) error {
m.primaryFieldIndecies = nil
for i := 0; i < m.typ.NumField(); i++ {
f := m.typ.Field(i)
tag, ok := f.Tag.Lookup("gosql")
if ok && tag == "-" {
continue
}
if ok && tag == "primary" {
if tag, ok := f.Tag.Lookup("idx"); ok && tag == "primary" {
m.primaryFieldIndecies = append(m.primaryFieldIndecies, i)
}
m.fields = append(m.fields, toSnakeCase(f.Name))
if tag, ok := f.Tag.Lookup("col"); ok {
if tag == "-" {
continue
}
m.fields = append(m.fields, tag)
} else {
m.fields = append(m.fields, toSnakeCase(f.Name))
}
}
if err := db.mustBeValid(m); err != nil {
return err
Expand Down Expand Up @@ -60,7 +63,7 @@ func (db *DB) mustBeValid(m *model) error {
return fmt.Errorf("model %s found more than once", m.name)
}
if len(m.primaryFieldIndecies) == 0 {
return fmt.Errorf("model %s must have at least one field tagged `gosql:\"primary\"`", m.name)
return fmt.Errorf("model %s must have at least one field tagged `idx:\"primary\"`", m.name)
}
return nil
}
Expand Down
53 changes: 34 additions & 19 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestDelete(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
}
deleteModel := T{5}
mock.ExpectExec(`^delete from t where id = \?$`).WithArgs(deleteModel.ID).WillReturnResult(sqlmock.NewResult(0, 1))
Expand All @@ -28,7 +28,7 @@ func TestUpdate(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
updateModel := T{5, "foo"}
Expand All @@ -42,7 +42,7 @@ func TestUpdateThreeFields(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
Email string
}
Expand All @@ -57,9 +57,9 @@ func TestUpdateThreeFieldsTwoPrimaries(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
Email string `gosql:"primary"`
Email string `idx:"primary"`
}
updateModel := T{5, "foo", "[email protected]"}
mock.ExpectExec(`^update t set name = \? where id = \? and email = \?$`).WithArgs(updateModel.Name, updateModel.ID, updateModel.Email).WillReturnResult(sqlmock.NewResult(0, 1))
Expand All @@ -81,7 +81,7 @@ func TestInsert(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
insertModel := T{Name: "foo"}
Expand All @@ -95,7 +95,7 @@ func TestInsertWithPrimary(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
insertModelWithPrimary := T{5, "foo"}
Expand All @@ -109,8 +109,8 @@ func TestInsertWithAllFieldsPrimary(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
Name string `gosql:"primary"`
ID int `idx:"primary"`
Name string `idx:"primary"`
}
model := T{5, "foo"}
mock.ExpectExec(`^insert into t \(id, name\) values \(\?, \?\)$`).WithArgs(model.ID, model.Name).WillReturnResult(sqlmock.NewResult(0, 1))
Expand All @@ -123,9 +123,9 @@ func TestInsertWith1stAndLastFieldsPrimary(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Email string
Name string `gosql:"primary"`
Name string `idx:"primary"`
}
model := T{5, "", "foo"}
mock.ExpectExec(`^insert into t \(id, email, name\) values \(\?, \?, \?\)$`).WithArgs(model.ID, model.Email, model.Name).WillReturnResult(sqlmock.NewResult(0, 1))
Expand All @@ -134,13 +134,28 @@ func TestInsertWith1stAndLastFieldsPrimary(t *testing.T) {
check(t, mock.ExpectationsWereMet())
}

func TestInsertWithOmittedField(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `idx:"primary"`
Email string
Name string `col:"-"`
}
model := T{5, "", "foo"}
mock.ExpectExec(`^insert into t \(id, email\) values \(\?, \?\)$`).WithArgs(model.ID, model.Email).WillReturnResult(sqlmock.NewResult(0, 1))
_, err = db.Insert(&model)
check(t, err)
check(t, mock.ExpectationsWereMet())
}

func ExampleDB_Insert() {
os.Remove("/tmp/foo.db")
sqliteDB, _ := sql.Open("sqlite3", "/tmp/foo.db")
sqliteDB.Exec("create table user (id integer not null primary key, name text); delete from user")
db := gosql.New(sqliteDB)
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
db.Insert(&User{Name: "Gopher"})
Expand All @@ -156,7 +171,7 @@ func ExampleDB_Update() {
sqliteDB.Exec("create table user (id integer not null primary key, name text, email text); delete from user")
db := gosql.New(sqliteDB)
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
Email string
}
Expand All @@ -177,7 +192,7 @@ func ExampleDB_Delete() {
sqliteDB.Exec("create table user (id integer not null primary key, name text); delete from user")
db := gosql.New(sqliteDB)
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
user := User{ID: 5, Name: "Gopher"}
Expand All @@ -192,7 +207,7 @@ func ExampleDB_Delete() {
func BenchmarkInsert(b *testing.B) {
db := getSQLiteDB(b, "create table user (id integer not null primary key, name text); delete from user")
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
user := User{Name: "Gopher"}
Expand All @@ -206,7 +221,7 @@ func BenchmarkInsert(b *testing.B) {
func BenchmarkUpdate(b *testing.B) {
db := getSQLiteDB(b, "create table user (id integer not null primary key, name text); delete from user")
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
user := User{Name: "Gopher"}
Expand All @@ -222,7 +237,7 @@ func BenchmarkUpdate(b *testing.B) {
func BenchmarkSelect(b *testing.B) {
db := getSQLiteDB(b, "create table user (id integer not null primary key, name text); delete from user")
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
user := User{ID: 5, Name: "Gopher"}
Expand All @@ -238,7 +253,7 @@ func BenchmarkSelect(b *testing.B) {
func BenchmarkSelectMany(b *testing.B) {
db := getSQLiteDB(b, "create table user (id integer not null primary key, name text); delete from user")
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
user := User{Name: "Gopher"}
Expand All @@ -256,7 +271,7 @@ func BenchmarkSelectMany(b *testing.B) {
func BenchmarkSelectManyPtrs(b *testing.B) {
db := getSQLiteDB(b, "create table user (id integer not null primary key, name text); delete from user")
type User struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name string
}
user := User{Name: "Gopher"}
Expand Down
4 changes: 2 additions & 2 deletions null_int64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestNullInt64Valid(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name gosql.NullInt64
}
control := T{
Expand All @@ -31,7 +31,7 @@ func TestNullInt64NotValid(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name gosql.NullInt64
}
control := T{
Expand Down
4 changes: 2 additions & 2 deletions null_string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestNullStringValid(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name gosql.NullString
}
control := T{
Expand All @@ -31,7 +31,7 @@ func TestNullStringNotValid(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name gosql.NullString
}
control := T{
Expand Down
4 changes: 2 additions & 2 deletions null_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func TestNullTimeValid(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name gosql.NullTime
}
control := T{
Expand All @@ -32,7 +32,7 @@ func TestNullTimeNotValid(t *testing.T) {
db, mock, err := getMockDB()
check(t, err)
type T struct {
ID int `gosql:"primary"`
ID int `idx:"primary"`
Name gosql.NullTime
}
control := T{
Expand Down
12 changes: 11 additions & 1 deletion select_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,11 @@ func (sq *SelectQuery) toOne(out interface{}) error {
for rows.Next() {
dests := make([]interface{}, fieldCount)
for j := 0; j < fieldCount; j++ {
dests[j] = e.Field(sq.model.getFieldIndexByName(columns[j])).Addr().Interface()
fieldIdx := sq.model.getFieldIndexByName(columns[j])
if fieldIdx < 0 {
return fmt.Errorf("no field for column %s", columns[j])
}
dests[j] = e.Field(fieldIdx).Addr().Interface()
}
if err := rows.Scan(dests...); err != nil {
return err
Expand Down Expand Up @@ -218,6 +222,9 @@ func (sq *SelectQuery) toMany(sliceType reflect.Type, outs interface{}) error {
fieldIndecies := make([]int, fieldCount)
for j := 0; j < fieldCount; j++ {
fieldIndecies[j] = sq.model.getFieldIndexByName(columns[j])
if fieldIndecies[j] < 0 {
return fmt.Errorf("no field for column %s", columns[j])
}
}
dests := make([]interface{}, fieldCount)
for rows.Next() {
Expand Down Expand Up @@ -253,6 +260,9 @@ func (sq *SelectQuery) toManyValues(sliceType reflect.Type, outs interface{}) er
fieldIndecies := make([]int, fieldCount)
for j := 0; j < fieldCount; j++ {
fieldIndecies[j] = sq.model.getFieldIndexByName(columns[j])
if fieldIndecies[j] < 0 {
return fmt.Errorf("no field for column %s", columns[j])
}
}
dests := make([]interface{}, fieldCount)
newOut := newOuts.Index(0)
Expand Down
Loading