From f36afb546df10439754cb0e407424b7e426569cf Mon Sep 17 00:00:00 2001 From: Patrik Date: Thu, 29 Oct 2020 14:22:36 +0100 Subject: [PATCH 01/59] fix: improve model ID field customization (#604) Updates places where `"id"` was hardcoded instead of using `model.IDField()`. --- columns/columns.go | 14 ++-- columns/columns_for_struct.go | 10 +-- columns/columns_test.go | 46 ++++++++++-- columns/readable_columns_test.go | 6 +- columns/writeable_columns_test.go | 8 +-- executors.go | 10 +-- executors_test.go | 70 +++++++++++++++++++ model.go | 18 ++++- pop_test.go | 5 ++ sql_builder.go | 4 +- .../20201028153041_non_standard_id.down.fizz | 1 + .../20201028153041_non_standard_id.up.fizz | 6 ++ 12 files changed, 166 insertions(+), 32 deletions(-) create mode 100644 testdata/migrations/20201028153041_non_standard_id.down.fizz create mode 100644 testdata/migrations/20201028153041_non_standard_id.up.fizz diff --git a/columns/columns.go b/columns/columns.go index 8ee8f15c..4ea26564 100644 --- a/columns/columns.go +++ b/columns/columns.go @@ -13,6 +13,7 @@ type Columns struct { lock *sync.RWMutex TableName string TableAlias string + IDField string } // Add a column to the list. @@ -74,7 +75,7 @@ func (c *Columns) Add(names ...string) []*Column { } else if xs[1] == "w" { col.Readable = false } - } else if col.Name == "id" { + } else if col.Name == c.IDField { col.Writeable = false } @@ -98,7 +99,7 @@ func (c *Columns) Remove(names ...string) { // Writeable gets a list of the writeable columns from the column list. func (c Columns) Writeable() *WriteableColumns { - w := &WriteableColumns{NewColumnsWithAlias(c.TableName, c.TableAlias)} + w := &WriteableColumns{NewColumnsWithAlias(c.TableName, c.TableAlias, c.IDField)} for _, col := range c.Cols { if col.Writeable { w.Cols[col.Name] = col @@ -109,7 +110,7 @@ func (c Columns) Writeable() *WriteableColumns { // Readable gets a list of the readable columns from the column list. func (c Columns) Readable() *ReadableColumns { - w := &ReadableColumns{NewColumnsWithAlias(c.TableName, c.TableAlias)} + w := &ReadableColumns{NewColumnsWithAlias(c.TableName, c.TableAlias, c.IDField)} for _, col := range c.Cols { if col.Readable { w.Cols[col.Name] = col @@ -157,17 +158,18 @@ func (c Columns) SymbolizedString() string { } // NewColumns constructs a list of columns for a given table name. -func NewColumns(tableName string) Columns { - return NewColumnsWithAlias(tableName, "") +func NewColumns(tableName, idField string) Columns { + return NewColumnsWithAlias(tableName, "", idField) } // NewColumnsWithAlias constructs a list of columns for a given table // name, using a given alias for the table. -func NewColumnsWithAlias(tableName string, tableAlias string) Columns { +func NewColumnsWithAlias(tableName, tableAlias, idField string) Columns { return Columns{ lock: &sync.RWMutex{}, Cols: map[string]*Column{}, TableName: tableName, TableAlias: tableAlias, + IDField: idField, } } diff --git a/columns/columns_for_struct.go b/columns/columns_for_struct.go index 22cdbebc..a20cd426 100644 --- a/columns/columns_for_struct.go +++ b/columns/columns_for_struct.go @@ -6,17 +6,17 @@ import ( // ForStruct returns a Columns instance for // the struct passed in. -func ForStruct(s interface{}, tableName string) (columns Columns) { - return ForStructWithAlias(s, tableName, "") +func ForStruct(s interface{}, tableName, idField string) (columns Columns) { + return ForStructWithAlias(s, tableName, "", idField) } // ForStructWithAlias returns a Columns instance for the struct passed in. // If the tableAlias is not empty, it will be used. -func ForStructWithAlias(s interface{}, tableName string, tableAlias string) (columns Columns) { - columns = NewColumnsWithAlias(tableName, tableAlias) +func ForStructWithAlias(s interface{}, tableName, tableAlias, idField string) (columns Columns) { + columns = NewColumnsWithAlias(tableName, tableAlias, idField) defer func() { if r := recover(); r != nil { - columns = NewColumnsWithAlias(tableName, tableAlias) + columns = NewColumnsWithAlias(tableName, tableAlias, idField) columns.Add("*") } }() diff --git a/columns/columns_test.go b/columns/columns_test.go index caa0716a..f4699dc4 100644 --- a/columns/columns_test.go +++ b/columns/columns_test.go @@ -21,8 +21,8 @@ type foos []foo func Test_Column_MapsSlice(t *testing.T) { r := require.New(t) - c1 := columns.ForStruct(&foo{}, "foo") - c2 := columns.ForStruct(&foos{}, "foo") + c1 := columns.ForStruct(&foo{}, "foo", "id") + c2 := columns.ForStruct(&foos{}, "foo", "id") r.Equal(c1.String(), c2.String()) } @@ -30,7 +30,7 @@ func Test_Columns_Basics(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") r.Equal(len(c.Cols), 4) r.Equal(c.Cols["first_name"], &columns.Column{Name: "first_name", Writeable: false, Readable: true, SelectSQL: "first_name as f"}) r.Equal(c.Cols["LastName"], &columns.Column{Name: "LastName", Writeable: true, Readable: true, SelectSQL: "foo.LastName"}) @@ -43,7 +43,7 @@ func Test_Columns_Add(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") r.Equal(len(c.Cols), 4) c.Add("foo", "first_name") r.Equal(len(c.Cols), 5) @@ -55,7 +55,7 @@ func Test_Columns_Remove(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") r.Equal(len(c.Cols), 4) c.Remove("foo", "first_name") r.Equal(len(c.Cols), 3) @@ -75,9 +75,43 @@ func (fooQuoter) Quote(key string) string { func Test_Columns_Sorted(t *testing.T) { r := require.New(t) - c := columns.ForStruct(fooWithSuffix{}, "fooWithSuffix") + c := columns.ForStruct(fooWithSuffix{}, "fooWithSuffix", "id") r.Equal(len(c.Cols), 2) r.Equal(c.SymbolizedString(), ":amount, :amount_units") r.Equal(c.String(), "amount, amount_units") r.Equal(c.QuotedString(fooQuoter{}), "`amount`, `amount_units`") } + +func Test_Columns_IDField(t *testing.T) { + type withID struct { + ID string `db:"id"` + } + + r := require.New(t) + c := columns.ForStruct(withID{}, "with_id", "id") + r.Equal(1, len(c.Cols), "%+v", c) + r.Equal(&columns.Column{Name: "id", Writeable: false, Readable: true, SelectSQL: "with_id.id"}, c.Cols["id"]) +} + +func Test_Columns_IDField_Readonly(t *testing.T) { + type withIDReadonly struct { + ID string `db:"id" rw:"r"` + } + + r := require.New(t) + c := columns.ForStruct(withIDReadonly{}, "with_id_readonly", "id") + r.Equal(1, len(c.Cols), "%+v", c) + r.Equal(&columns.Column{Name: "id", Writeable: false, Readable: true, SelectSQL: "with_id_readonly.id"}, c.Cols["id"]) +} + +func Test_Columns_ID_Field_Not_ID(t *testing.T) { + type withNonStandardID struct { + PK string `db:"notid"` + } + + r := require.New(t) + + c := columns.ForStruct(withNonStandardID{}, "non_standard_id", "notid") + r.Equal(1, len(c.Cols), "%+v", c) + r.Equal(&columns.Column{Name: "notid", Writeable: false, Readable: true, SelectSQL: "non_standard_id.notid"}, c.Cols["notid"]) +} diff --git a/columns/readable_columns_test.go b/columns/readable_columns_test.go index 8394b967..a563d789 100644 --- a/columns/readable_columns_test.go +++ b/columns/readable_columns_test.go @@ -10,7 +10,7 @@ import ( func Test_Columns_ReadableString(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") u := c.Readable().String() r.Equal(u, "LastName, first_name, read") } @@ -19,7 +19,7 @@ func Test_Columns_ReadableString(t *testing.T) { func Test_Columns_Readable_SelectString(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") u := c.Readable().SelectString() r.Equal(u, "first_name as f, foo.LastName, foo.read") } @@ -28,7 +28,7 @@ func Test_Columns_Readable_SelectString(t *testing.T) { func Test_Columns_ReadableString_Symbolized(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") u := c.Readable().SymbolizedString() r.Equal(u, ":LastName, :first_name, :read") } diff --git a/columns/writeable_columns_test.go b/columns/writeable_columns_test.go index 269735f3..053dbdaf 100644 --- a/columns/writeable_columns_test.go +++ b/columns/writeable_columns_test.go @@ -10,7 +10,7 @@ import ( func Test_Columns_WriteableString_Symbolized(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") u := c.Writeable().SymbolizedString() r.Equal(u, ":LastName, :write") } @@ -19,7 +19,7 @@ func Test_Columns_WriteableString_Symbolized(t *testing.T) { func Test_Columns_UpdateString(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") u := c.Writeable().UpdateString() r.Equal(u, "LastName = :LastName, write = :write") } @@ -35,7 +35,7 @@ func Test_Columns_QuotedUpdateString(t *testing.T) { r := require.New(t) q := testQuoter{} for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") u := c.Writeable().QuotedUpdateString(q) r.Equal(u, "\"LastName\" = :LastName, \"write\" = :write") } @@ -44,7 +44,7 @@ func Test_Columns_QuotedUpdateString(t *testing.T) { func Test_Columns_WriteableString(t *testing.T) { r := require.New(t) for _, f := range []interface{}{foo{}, &foo{}} { - c := columns.ForStruct(f, "foo") + c := columns.ForStruct(f, "foo", "id") u := c.Writeable().String() r.Equal(u, "LastName, write") } diff --git a/executors.go b/executors.go index 9704c919..b3560141 100644 --- a/executors.go +++ b/executors.go @@ -228,7 +228,7 @@ func (c *Connection) Create(model interface{}, excludeColumns ...string) error { } tn := m.TableName() - cols := columns.ForStructWithAlias(m.Value, tn, m.As) + cols := m.Columns() if tn == sm.TableName() { cols.Remove(excludeColumns...) @@ -350,8 +350,8 @@ func (c *Connection) Update(model interface{}, excludeColumns ...string) error { } tn := m.TableName() - cols := columns.ForStructWithAlias(model, tn, m.As) - cols.Remove("id", "created_at") + cols := columns.ForStructWithAlias(model, tn, m.As, m.IDField()) + cols.Remove(m.IDField(), "created_at") if tn == sm.TableName() { cols.Remove(excludeColumns...) @@ -393,11 +393,11 @@ func (c *Connection) UpdateColumns(model interface{}, columnNames ...string) err cols := columns.Columns{} if len(columnNames) > 0 && tn == sm.TableName() { - cols = columns.NewColumnsWithAlias(tn, m.As) + cols = columns.NewColumnsWithAlias(tn, m.As, sm.IDField()) cols.Add(columnNames...) } else { - cols = columns.ForStructWithAlias(model, tn, m.As) + cols = columns.ForStructWithAlias(model, tn, m.As, m.IDField()) } cols.Remove("id", "created_at") diff --git a/executors_test.go b/executors_test.go index 4fb4bb74..bee9a5e8 100644 --- a/executors_test.go +++ b/executors_test.go @@ -510,6 +510,28 @@ func Test_Create_With_Non_ID_PK_String(t *testing.T) { }) } +func Test_Create_Non_PK_ID(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + r.NoError(tx.Create(&NonStandardID{OutfacingID: "make sure the tested entry does not have pk=0"})) + + count, err := tx.Count(&NonStandardID{}) + entry := &NonStandardID{ + OutfacingID: "beautiful to the outside ID", + } + r.NoError(tx.Create(entry)) + + ctx, err := tx.Count(&NonStandardID{}) + r.NoError(err) + r.Equal(count+1, ctx) + r.NotZero(entry.ID) + }) +} + func Test_Eager_Create_Has_Many(t *testing.T) { if PDB == nil { t.Skip("skipping integration tests") @@ -1470,6 +1492,54 @@ func Test_Update_UUID(t *testing.T) { }) } +func Test_Update_With_Non_ID_PK(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + r.NoError(tx.Create(&CrookedColour{Name: "cc is not the first one"})) + + cc := CrookedColour{ + Name: "You?", + } + err := tx.Create(&cc) + r.NoError(err) + r.NotZero(cc.ID) + id := cc.ID + + updatedName := "Me!" + cc.Name = updatedName + r.NoError(tx.Update(&cc)) + r.Equal(id, cc.ID) + + r.NoError(tx.Reload(&cc)) + r.Equal(updatedName, cc.Name) + r.Equal(id, cc.ID) + }) +} + +func Test_Update_Non_PK_ID(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + client := &NonStandardID{ + OutfacingID: "my awesome hydra client", + } + r.NoError(tx.Create(client)) + + updatedID := "your awesome hydra client" + client.OutfacingID = updatedID + r.NoError(tx.Update(client)) + r.NoError(tx.Reload(client)) + r.Equal(updatedID, client.OutfacingID) + }) +} + func Test_Destroy(t *testing.T) { if PDB == nil { t.Skip("skipping integration tests") diff --git a/model.go b/model.go index 62efd25b..58019f73 100644 --- a/model.go +++ b/model.go @@ -2,6 +2,7 @@ package pop import ( "fmt" + "github.com/gobuffalo/pop/v5/columns" "github.com/pkg/errors" "reflect" "sync" @@ -46,7 +47,18 @@ func (m *Model) ID() interface{} { // IDField returns the name of the DB field used for the ID. // By default, it will return "id". func (m *Model) IDField() string { - field, ok := reflect.TypeOf(m.Value).Elem().FieldByName("ID") + modelType := reflect.TypeOf(m.Value) + + // remove all indirections + for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Ptr || modelType.Kind() == reflect.Array { + modelType = modelType.Elem() + } + + if modelType.Kind() == reflect.String { + return "id" + } + + field, ok := modelType.FieldByName("ID") if !ok { return "id" } @@ -101,6 +113,10 @@ func (m *Model) TableName() string { return tableMap[cacheKey] } +func (m *Model) Columns() columns.Columns { + return columns.ForStructWithAlias(m.Value, m.TableName(), m.As, m.IDField()) +} + func (m *Model) cacheKey(t reflect.Type) string { return t.PkgPath() + "." + t.Name() } diff --git a/pop_test.go b/pop_test.go index 33efcbe2..4ac25b68 100644 --- a/pop_test.go +++ b/pop_test.go @@ -419,3 +419,8 @@ type CrookedSong struct { CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` } + +type NonStandardID struct { + ID int `db:"pk"` + OutfacingID string `db:"id"` +} diff --git a/sql_builder.go b/sql_builder.go index 4ce35703..edd05c46 100644 --- a/sql_builder.go +++ b/sql_builder.go @@ -229,7 +229,7 @@ func (sq *sqlBuilder) buildColumns() columns.Columns { if ok && cols.TableAlias == asName { return cols } - cols = columns.ForStructWithAlias(sq.Model.Value, tableName, asName) + cols = columns.ForStructWithAlias(sq.Model.Value, tableName, asName, sq.Model.IDField()) columnCacheMutex.Lock() columnCache[tableName] = cols columnCacheMutex.Unlock() @@ -237,7 +237,7 @@ func (sq *sqlBuilder) buildColumns() columns.Columns { } // acl > 0 - cols := columns.NewColumns("") + cols := columns.NewColumns("", sq.Model.IDField()) cols.Add(sq.AddColumns...) return cols } diff --git a/testdata/migrations/20201028153041_non_standard_id.down.fizz b/testdata/migrations/20201028153041_non_standard_id.down.fizz new file mode 100644 index 00000000..5c56284f --- /dev/null +++ b/testdata/migrations/20201028153041_non_standard_id.down.fizz @@ -0,0 +1 @@ +drop_table("non_standard_ids") diff --git a/testdata/migrations/20201028153041_non_standard_id.up.fizz b/testdata/migrations/20201028153041_non_standard_id.up.fizz new file mode 100644 index 00000000..7590e4b4 --- /dev/null +++ b/testdata/migrations/20201028153041_non_standard_id.up.fizz @@ -0,0 +1,6 @@ +create_table("non_standard_ids") { + t.Column("pk", "int", { primary: true }) + t.Column("id", "string", {}) + + t.DisableTimestamps() +} From 4d0d8261cce2fc495c48bd8c8a45faf79de4f526 Mon Sep 17 00:00:00 2001 From: Michael Montgomery Date: Tue, 15 Dec 2020 14:17:00 -0600 Subject: [PATCH 02/59] Ensure uninitialized map is initialized when unmarshaling json Add tests for this scenario --- slices/map.go | 3 +++ slices/map_test.go | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/slices/map.go b/slices/map.go index d7f58ed4..c99e8a13 100644 --- a/slices/map.go +++ b/slices/map.go @@ -51,6 +51,9 @@ func (m Map) UnmarshalJSON(b []byte) error { if err != nil { return err } + if m == nil { + m = Map{} + } for key, value := range stuff { m[key] = value } diff --git a/slices/map_test.go b/slices/map_test.go index e5d4963b..265d9940 100644 --- a/slices/map_test.go +++ b/slices/map_test.go @@ -24,3 +24,14 @@ func Test_Map_MarshalJSON(t *testing.T) { r.NoError(err) r.Equal([]byte(`{"a":"b"}`), b) } + +func Test_Map_UnMarshalJSON_uninitialized_map_does_not_panic(t *testing.T) { + r := require.New(t) + + maps := make([]Map, 0) + r.NotPanics(func() { + err := json.Unmarshal([]byte(`[{"a": "b"}]`), &maps) + r.NoError(err) + r.Len(maps, 1) + }) +} From 81e5f2de71e12f851046ee3b943a2ff210cc2033 Mon Sep 17 00:00:00 2001 From: kyrozetera Date: Tue, 22 Dec 2020 23:54:35 -0600 Subject: [PATCH 03/59] exclude migration_table_name from connection string --- connection_details.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/connection_details.go b/connection_details.go index 76c165b5..29c0ae41 100644 --- a/connection_details.go +++ b/connection_details.go @@ -179,6 +179,10 @@ func (cd *ConnectionDetails) OptionsString(s string) string { } if cd.Options != nil { for k, v := range cd.Options { + if k == "migration_table_name" { + continue + } + s = fmt.Sprintf("%s&%s=%s", s, k, v) } } From 0e3d2e2e96149bd7e531cfbd8173dd3d30509e27 Mon Sep 17 00:00:00 2001 From: kyrozetera Date: Tue, 22 Dec 2020 23:54:51 -0600 Subject: [PATCH 04/59] add test for OptionsString --- connection_details_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/connection_details_test.go b/connection_details_test.go index 4121745a..877c8418 100644 --- a/connection_details_test.go +++ b/connection_details_test.go @@ -84,3 +84,22 @@ func Test_ConnectionDetails_Finalize_NoDB_NoURL(t *testing.T) { err := cd.Finalize() r.Error(err) } + +func Test_ConnectionDetails_OptionsString_Postgres(t *testing.T) { + r := require.New(t) + cd := &ConnectionDetails{ + Dialect: "postgres", + Database: "database", + Host: "host", + Port: "1234", + User: "user", + Password: "pass", + Options: map[string]string{ + "migration_table_name": "migrations", + "sslmode": "require", + }, + } + + r.Equal("sslmode=require", cd.OptionsString("")) + r.Equal("migrations", cd.MigrationTableName()) +} From b2918a3e163310d490636536ea11d8cba5b979cc Mon Sep 17 00:00:00 2001 From: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Date: Tue, 5 Jan 2021 02:55:39 -0500 Subject: [PATCH 05/59] Add support for pointer FKs when preloading a belongs_to association (#602) --- pop_test.go | 18 +++++----- preload_associations.go | 17 ++++++++-- preload_associations_test.go | 33 +++++++++++++++++++ .../migrations/20181104135856_taxis.up.fizz | 3 +- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/pop_test.go b/pop_test.go index 4ac25b68..1d473de0 100644 --- a/pop_test.go +++ b/pop_test.go @@ -138,14 +138,16 @@ type Book struct { } type Taxi struct { - ID int `db:"id"` - Model string `db:"model"` - UserID nulls.Int `db:"user_id"` - AddressID nulls.Int `db:"address_id"` - Driver *User `belongs_to:"user" fk_id:"user_id"` - Address Address `belongs_to:"address"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ID int `db:"id"` + Model string `db:"model"` + UserID nulls.Int `db:"user_id"` + AddressID nulls.Int `db:"address_id"` + Driver *User `belongs_to:"user" fk_id:"user_id"` + Address Address `belongs_to:"address"` + ToAddressID *int `db:"to_address_id"` + ToAddress *Address `belongs_to:"address"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` } // Validate gets run every time you call a "Validate*" (ValidateAndSave, ValidateAndCreate, ValidateAndUpdate) method. diff --git a/preload_associations.go b/preload_associations.go index 4a03b579..8ddea3c9 100644 --- a/preload_associations.go +++ b/preload_associations.go @@ -355,7 +355,9 @@ func preloadBelongsTo(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMetaI fkids := []interface{}{} mmi.iterate(func(val reflect.Value) { - fkids = append(fkids, mmi.mapper.FieldByName(val, fi.Path).Interface()) + if !isFieldNilPtr(val, fi) { + fkids = append(fkids, mmi.mapper.FieldByName(val, fi.Path).Interface()) + } }) if len(fkids) == 0 { @@ -386,11 +388,15 @@ func preloadBelongsTo(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMetaI // 3) iterate over every model and fill it with the assoc. mmi.iterate(func(mvalue reflect.Value) { + if isFieldNilPtr(mvalue, fi) { + return + } modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) for i := 0; i < slice.Elem().Len(); i++ { asocValue := slice.Elem().Index(i) - if mmi.mapper.FieldByName(mvalue, fi.Path).Interface() == mmi.mapper.FieldByName(asocValue, "ID").Interface() || - reflect.DeepEqual(mmi.mapper.FieldByName(mvalue, fi.Path), mmi.mapper.FieldByName(asocValue, "ID")) { + fkField := reflect.Indirect(mmi.mapper.FieldByName(mvalue, fi.Path)) + if fkField.Interface() == mmi.mapper.FieldByName(asocValue, "ID").Interface() || + reflect.DeepEqual(fkField, mmi.mapper.FieldByName(asocValue, "ID")) { switch { case modelAssociationField.Kind() == reflect.Slice || modelAssociationField.Kind() == reflect.Array: @@ -499,3 +505,8 @@ func preloadManyToMany(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMeta } return nil } + +func isFieldNilPtr(val reflect.Value, fi *reflectx.FieldInfo) bool { + fieldValue := reflectx.FieldByIndexesReadOnly(val, fi.Index) + return fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() +} diff --git a/preload_associations_test.go b/preload_associations_test.go index af1f392f..9d735fd4 100644 --- a/preload_associations_test.go +++ b/preload_associations_test.go @@ -231,3 +231,36 @@ func Test_New_Implementation_For_BelongsTo_Multiple_Fields(t *testing.T) { SetEagerMode(EagerDefault) }) } + +func Test_New_Implementation_For_BelongsTo_Ptr_Field(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + a := require.New(t) + toAddress := Address{HouseNumber: 1, Street: "Destination Ave"} + a.NoError(tx.Create(&toAddress)) + + taxi := Taxi{ToAddressID: &toAddress.ID} + a.NoError(tx.Create(&taxi)) + + book1 := Book{TaxiID: nulls.NewInt(taxi.ID), Title: "My Book"} + a.NoError(tx.Create(&book1)) + + taxiNilToAddress := Taxi{ToAddressID: nil} + a.NoError(tx.Create(&taxiNilToAddress)) + + book2 := Book{TaxiID: nulls.NewInt(taxiNilToAddress.ID), Title: "Another Book"} + a.NoError(tx.Create(&book2)) + + SetEagerMode(EagerPreload) + books := []Book{} + a.NoError(tx.EagerPreload("Taxi.ToAddress").Order("created_at").All(&books)) + a.Len(books, 2) + a.Equal(toAddress.Street, books[0].Taxi.ToAddress.Street) + a.NotNil(books[0].Taxi.ToAddressID) + a.Nil(books[1].Taxi.ToAddress) + a.Nil(books[1].Taxi.ToAddressID) + SetEagerMode(EagerDefault) + }) +} diff --git a/testdata/migrations/20181104135856_taxis.up.fizz b/testdata/migrations/20181104135856_taxis.up.fizz index 9cf85238..a11185c0 100644 --- a/testdata/migrations/20181104135856_taxis.up.fizz +++ b/testdata/migrations/20181104135856_taxis.up.fizz @@ -2,6 +2,7 @@ create_table("taxis") { t.Column("id", "int", {primary: true}) t.Column("model", "string", {}) t.Column("user_id", "int", {"null": true}) - t.Column("address_id", "int",{"null":true}) + t.Column("address_id", "int", {"null":true}) + t.Column("to_address_id", "int", {"null":true}) t.Timestamps() } \ No newline at end of file From 0fb7635ebe36962f0253be169a12f71e2331adc7 Mon Sep 17 00:00:00 2001 From: hackerman <3372410+aeneasr@users.noreply.github.com> Date: Mon, 18 Jan 2021 21:37:33 +0100 Subject: [PATCH 06/59] feat: support context-aware tablenames (#614) This patch adds a feature which enables pop to pass down the connection context to the model's TableName() function by implementing TableName(ctx context.Context) string. The context can be used to dynamically generate tablenames which can be important for prefixed or generic tables and other use cases. --- belongs_to.go | 8 +- belongs_to_test.go | 7 +- connection.go | 10 ++ connection_details.go | 3 +- connection_instrumented.go | 1 + connection_instrumented_nosqlite_test.go | 3 +- connection_instrumented_test.go | 5 +- dialect_sqlite.go | 3 +- executors.go | 28 ++--- finders.go | 14 +-- finders_test.go | 2 +- match_test.go | 3 +- migration_info_test.go | 3 +- model.go | 93 +++++++++------ model_context_test.go | 109 +++++++++++++++++ model_test.go | 111 ++++++++++++++---- preload_associations.go | 2 +- query_test.go | 15 +-- scopes_test.go | 3 +- soda/cmd/migrate_status.go | 3 +- store.go | 4 + .../20210104145901_context_tables.down.fizz | 2 + .../20210104145901_context_tables.up.fizz | 9 ++ testdata/models/ac/user.go | 9 ++ testdata/models/bc/user.go | 9 ++ validations.go | 2 +- 26 files changed, 357 insertions(+), 104 deletions(-) create mode 100644 model_context_test.go create mode 100644 testdata/migrations/20210104145901_context_tables.down.fizz create mode 100644 testdata/migrations/20210104145901_context_tables.up.fizz create mode 100644 testdata/models/ac/user.go create mode 100644 testdata/models/bc/user.go diff --git a/belongs_to.go b/belongs_to.go index 0b5c977e..d261a315 100644 --- a/belongs_to.go +++ b/belongs_to.go @@ -19,7 +19,7 @@ func (c *Connection) BelongsToAs(model interface{}, as string) *Query { // BelongsTo adds a "where" clause based on the "ID" of the // "model" passed into it. func (q *Query) BelongsTo(model interface{}) *Query { - m := &Model{Value: model} + m := NewModel(model, q.Connection.Context()) q.Where(fmt.Sprintf("%s = ?", m.associationName()), m.ID()) return q } @@ -27,7 +27,7 @@ func (q *Query) BelongsTo(model interface{}) *Query { // BelongsToAs adds a "where" clause based on the "ID" of the // "model" passed into it, using an alias. func (q *Query) BelongsToAs(model interface{}, as string) *Query { - m := &Model{Value: model} + m := NewModel(model, q.Connection.Context()) q.Where(fmt.Sprintf("%s = ?", as), m.ID()) return q } @@ -42,8 +42,8 @@ func (c *Connection) BelongsToThrough(bt, thru interface{}) *Query { // through the associated "thru" model. func (q *Query) BelongsToThrough(bt, thru interface{}) *Query { q.belongsToThroughClauses = append(q.belongsToThroughClauses, belongsToThroughClause{ - BelongsTo: &Model{Value: bt}, - Through: &Model{Value: thru}, + BelongsTo: NewModel(bt, q.Connection.Context()), + Through: NewModel(thru, q.Connection.Context()), }) return q } diff --git a/belongs_to_test.go b/belongs_to_test.go index e4e3a3e7..9eb99914 100644 --- a/belongs_to_test.go +++ b/belongs_to_test.go @@ -1,6 +1,7 @@ package pop import ( + "context" "testing" "github.com/stretchr/testify/require" @@ -14,7 +15,7 @@ func Test_BelongsTo(t *testing.T) { q := PDB.BelongsTo(&User{ID: 1}) - m := &Model{Value: &Enemy{}} + m := NewModel(new(Enemy), context.Background()) sql, _ := q.ToSQL(m) r.Equal(ts("SELECT enemies.A FROM enemies AS enemies WHERE user_id = ?"), sql) @@ -28,7 +29,7 @@ func Test_BelongsToAs(t *testing.T) { q := PDB.BelongsToAs(&User{ID: 1}, "u_id") - m := &Model{Value: &Enemy{}} + m := NewModel(new(Enemy), context.Background()) sql, _ := q.ToSQL(m) r.Equal(ts("SELECT enemies.A FROM enemies AS enemies WHERE u_id = ?"), sql) @@ -43,7 +44,7 @@ func Test_BelongsToThrough(t *testing.T) { q := PDB.BelongsToThrough(&User{ID: 1}, &Friend{}) qs := "SELECT enemies.A FROM enemies AS enemies, good_friends AS good_friends WHERE good_friends.user_id = ? AND enemies.id = good_friends.enemy_id" - m := &Model{Value: &Enemy{}} + m := NewModel(new(Enemy), context.Background()) sql, _ := q.ToSQL(m) r.Equal(ts(qs), sql) } diff --git a/connection.go b/connection.go index df116fb3..6e0f55ee 100644 --- a/connection.go +++ b/connection.go @@ -33,6 +33,16 @@ func (c *Connection) URL() string { return c.Dialect.URL() } +// Context returns the connection's context set by "Context()" or context.TODO() +// if no context is set. +func (c *Connection) Context() context.Context { + if c, ok := c.Store.(interface{ Context() context.Context }); ok { + return c.Context() + } + + return context.TODO() +} + // MigrationURL returns the datasource connection string used for running the migrations func (c *Connection) MigrationURL() string { return c.Dialect.MigrationURL() diff --git a/connection_details.go b/connection_details.go index 29c0ae41..6456b7d1 100644 --- a/connection_details.go +++ b/connection_details.go @@ -2,13 +2,14 @@ package pop import ( "fmt" - "github.com/luna-duclos/instrumentedsql" "net/url" "regexp" "strconv" "strings" "time" + "github.com/luna-duclos/instrumentedsql" + "github.com/gobuffalo/pop/v5/internal/defaults" "github.com/gobuffalo/pop/v5/logging" "github.com/pkg/errors" diff --git a/connection_instrumented.go b/connection_instrumented.go index 84cf7820..f2d46b02 100644 --- a/connection_instrumented.go +++ b/connection_instrumented.go @@ -3,6 +3,7 @@ package pop import ( "database/sql" "database/sql/driver" + mysqld "github.com/go-sql-driver/mysql" "github.com/gobuffalo/pop/v5/logging" pgx "github.com/jackc/pgx/v4/stdlib" diff --git a/connection_instrumented_nosqlite_test.go b/connection_instrumented_nosqlite_test.go index 715a92ab..2cf6ae01 100644 --- a/connection_instrumented_nosqlite_test.go +++ b/connection_instrumented_nosqlite_test.go @@ -3,8 +3,9 @@ package pop import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestInstrumentation_WithoutSqlite(t *testing.T) { diff --git a/connection_instrumented_test.go b/connection_instrumented_test.go index d5125639..808d8638 100644 --- a/connection_instrumented_test.go +++ b/connection_instrumented_test.go @@ -3,12 +3,13 @@ package pop import ( "context" "fmt" - "github.com/luna-duclos/instrumentedsql" - "github.com/stretchr/testify/suite" "os" "strings" "sync" "time" + + "github.com/luna-duclos/instrumentedsql" + "github.com/stretchr/testify/suite" ) func testInstrumentedDriver(p *suite.Suite) { diff --git a/dialect_sqlite.go b/dialect_sqlite.go index b3045090..47bc3e28 100644 --- a/dialect_sqlite.go +++ b/dialect_sqlite.go @@ -5,7 +5,6 @@ package pop import ( "database/sql/driver" "fmt" - "github.com/mattn/go-sqlite3" "io" "net/url" "os" @@ -15,6 +14,8 @@ import ( "sync" "time" + "github.com/mattn/go-sqlite3" + "github.com/gobuffalo/fizz" "github.com/gobuffalo/fizz/translators" _ "github.com/mattn/go-sqlite3" // Load SQLite3 CGo driver diff --git a/executors.go b/executors.go index b3560141..657ecea7 100644 --- a/executors.go +++ b/executors.go @@ -13,7 +13,7 @@ import ( // Reload fetch fresh data for a given model, using its ID. func (c *Connection) Reload(model interface{}) error { - sm := Model{Value: model} + sm := NewModel(model, c.Context()) return sm.iterate(func(m *Model) error { return c.Find(m.Value, m.ID()) }) @@ -51,7 +51,7 @@ func (q *Query) ExecWithCount() (int, error) { // // If model is a slice, each item of the slice is validated then saved in the database. func (c *Connection) ValidateAndSave(model interface{}, excludeColumns ...string) (*validate.Errors, error) { - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) if err := sm.beforeValidate(c); err != nil { return nil, err } @@ -77,7 +77,7 @@ func IsZeroOfUnderlyingType(x interface{}) bool { // // If model is a slice, each item of the slice is saved in the database. func (c *Connection) Save(model interface{}, excludeColumns ...string) error { - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) return sm.iterate(func(m *Model) error { id, err := m.fieldByName("ID") if err != nil { @@ -95,7 +95,7 @@ func (c *Connection) Save(model interface{}, excludeColumns ...string) error { // // If model is a slice, each item of the slice is validated then created in the database. func (c *Connection) ValidateAndCreate(model interface{}, excludeColumns ...string) (*validate.Errors, error) { - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) if err := sm.beforeValidate(c); err != nil { return nil, err } @@ -126,7 +126,7 @@ func (c *Connection) ValidateAndCreate(model interface{}, excludeColumns ...stri continue } - sm := &Model{Value: i} + sm := NewModel(i, c.Context()) verrs, err := sm.validateAndOnlyCreate(c) if err != nil || verrs.HasAny() { return verrs, err @@ -140,14 +140,14 @@ func (c *Connection) ValidateAndCreate(model interface{}, excludeColumns ...stri continue } - sm := &Model{Value: i} + sm := NewModel(i, c.Context()) verrs, err := sm.validateAndOnlyCreate(c) if err != nil || verrs.HasAny() { return verrs, err } } - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) verrs, err = sm.validateCreate(c) if err != nil || verrs.HasAny() { return verrs, err @@ -170,7 +170,7 @@ func (c *Connection) Create(model interface{}, excludeColumns ...string) error { c.disableEager() - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) return sm.iterate(func(m *Model) error { return c.timeFunc("Create", func() error { var localIsEager = isEager @@ -203,7 +203,7 @@ func (c *Connection) Create(model interface{}, excludeColumns ...string) error { } if localIsEager { - sm := &Model{Value: i} + sm := NewModel(i, c.Context()) err = sm.iterate(func(m *Model) error { id, err := m.fieldByName("ID") if err != nil { @@ -255,7 +255,7 @@ func (c *Connection) Create(model interface{}, excludeColumns ...string) error { continue } - sm := &Model{Value: i} + sm := NewModel(i, c.Context()) err = sm.iterate(func(m *Model) error { fbn, err := m.fieldByName("ID") if err != nil { @@ -318,7 +318,7 @@ func (c *Connection) Create(model interface{}, excludeColumns ...string) error { // // If model is a slice, each item of the slice is validated then updated in the database. func (c *Connection) ValidateAndUpdate(model interface{}, excludeColumns ...string) (*validate.Errors, error) { - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) if err := sm.beforeValidate(c); err != nil { return nil, err } @@ -337,7 +337,7 @@ func (c *Connection) ValidateAndUpdate(model interface{}, excludeColumns ...stri // // If model is a slice, each item of the slice is updated in the database. func (c *Connection) Update(model interface{}, excludeColumns ...string) error { - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) return sm.iterate(func(m *Model) error { return c.timeFunc("Update", func() error { var err error @@ -377,7 +377,7 @@ func (c *Connection) Update(model interface{}, excludeColumns ...string) error { // // If model is a slice, each item of the slice is updated in the database. func (c *Connection) UpdateColumns(model interface{}, columnNames ...string) error { - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) return sm.iterate(func(m *Model) error { return c.timeFunc("Update", func() error { var err error @@ -419,7 +419,7 @@ func (c *Connection) UpdateColumns(model interface{}, columnNames ...string) err // // If model is a slice, each item of the slice is deleted from the database. func (c *Connection) Destroy(model interface{}) error { - sm := &Model{Value: model} + sm := NewModel(model, c.Context()) return sm.iterate(func(m *Model) error { return c.timeFunc("Destroy", func() error { var err error diff --git a/finders.go b/finders.go index 9026d14b..fa1a220a 100644 --- a/finders.go +++ b/finders.go @@ -29,7 +29,7 @@ func (c *Connection) Find(model interface{}, id interface{}) error { // // q.Find(&User{}, 1) func (q *Query) Find(model interface{}, id interface{}) error { - m := &Model{Value: model} + m := NewModel(model, q.Connection.Context()) idq := m.whereID() switch t := id.(type) { case uuid.UUID: @@ -69,7 +69,7 @@ func (c *Connection) First(model interface{}) error { func (q *Query) First(model interface{}) error { err := q.Connection.timeFunc("First", func() error { q.Limit(1) - m := &Model{Value: model} + m := NewModel(model, q.Connection.Context()) if err := q.Connection.Dialect.SelectOne(q.Connection.Store, m, *q); err != nil { return err } @@ -102,7 +102,7 @@ func (q *Query) Last(model interface{}) error { err := q.Connection.timeFunc("Last", func() error { q.Limit(1) q.Order("created_at DESC, id DESC") - m := &Model{Value: model} + m := NewModel(model, q.Connection.Context()) if err := q.Connection.Dialect.SelectOne(q.Connection.Store, m, *q); err != nil { return err } @@ -134,7 +134,7 @@ func (c *Connection) All(models interface{}) error { // q.Where("name = ?", "mark").All(&[]User{}) func (q *Query) All(models interface{}) error { err := q.Connection.timeFunc("All", func() error { - m := &Model{Value: models} + m := NewModel(models, q.Connection.Context()) err := q.Connection.Dialect.SelectMany(q.Connection.Store, m, *q) if err != nil { return err @@ -258,7 +258,7 @@ func (q *Query) eagerDefaultAssociations(model interface{}) error { } } - sqlSentence, args := query.ToSQL(&Model{Value: association.Interface()}) + sqlSentence, args := query.ToSQL(NewModel(association.Interface(), query.Connection.Context())) query = query.RawQuery(sqlSentence, args...) if association.Kind() == reflect.Slice || association.Kind() == reflect.Array { @@ -302,7 +302,7 @@ func (q *Query) Exists(model interface{}) (bool, error) { tmpQuery.Paginator = nil tmpQuery.orderClauses = clauses{} tmpQuery.limitResults = 0 - query, args := tmpQuery.ToSQL(&Model{Value: model}) + query, args := tmpQuery.ToSQL(NewModel(model, tmpQuery.Connection.Context())) // when query contains custom selected fields / executed using RawQuery, // sql may already contains limit and offset @@ -348,7 +348,7 @@ func (q Query) CountByField(model interface{}, field string) (int, error) { tmpQuery.Paginator = nil tmpQuery.orderClauses = clauses{} tmpQuery.limitResults = 0 - query, args := tmpQuery.ToSQL(&Model{Value: model}) + query, args := tmpQuery.ToSQL(NewModel(model, q.Connection.Context())) // when query contains custom selected fields / executed using RawQuery, // sql may already contains limit and offset diff --git a/finders_test.go b/finders_test.go index 389dc80a..7f30727e 100644 --- a/finders_test.go +++ b/finders_test.go @@ -101,7 +101,7 @@ func Test_Select(t *testing.T) { q := tx.Select("name", "email", "\n", "\t\n", "") - sm := &Model{Value: &User{}} + sm := NewModel(new(User), tx.Context()) sql, _ := q.ToSQL(sm) r.Equal(tx.Dialect.TranslateSQL("SELECT email, name FROM users AS users"), sql) diff --git a/match_test.go b/match_test.go index 8cc41a6b..0f1591f1 100644 --- a/match_test.go +++ b/match_test.go @@ -1,8 +1,9 @@ package pop import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func Test_ParseMigrationFilenameFizzDown(t *testing.T) { diff --git a/migration_info_test.go b/migration_info_test.go index 0f76824e..f2174551 100644 --- a/migration_info_test.go +++ b/migration_info_test.go @@ -1,9 +1,10 @@ package pop import ( - "github.com/stretchr/testify/assert" "sort" "testing" + + "github.com/stretchr/testify/assert" ) func TestSortingMigrations(t *testing.T) { diff --git a/model.go b/model.go index 58019f73..1dea97f5 100644 --- a/model.go +++ b/model.go @@ -1,23 +1,23 @@ package pop import ( + "context" "fmt" - "github.com/gobuffalo/pop/v5/columns" - "github.com/pkg/errors" "reflect" - "sync" + "strings" "time" - "github.com/gobuffalo/flect" nflect "github.com/gobuffalo/flect/name" + + "github.com/gobuffalo/pop/v5/columns" + "github.com/pkg/errors" + + "github.com/gobuffalo/flect" "github.com/gofrs/uuid" ) var nowFunc = time.Now -var tableMap = map[string]string{} -var tableMapMu = sync.RWMutex{} - // Value is the contents of a `Model`. type Value interface{} @@ -27,8 +27,13 @@ type modelIterable func(*Model) error // that is passed in to many functions. type Model struct { Value - tableName string - As string + ctx context.Context + As string +} + +// NewModel returns a new model with the specified value and context. +func NewModel(v Value, ctx context.Context) *Model { + return &Model{Value: v, ctx: ctx} } // ID returns the ID of the Model. All models must have an `ID` field this is @@ -86,31 +91,32 @@ type TableNameAble interface { TableName() string } +// TableNameAbleWithContext is equal to TableNameAble but will +// be passed the queries' context. Useful in cases where the +// table name depends on e.g. +type TableNameAbleWithContext interface { + TableName(ctx context.Context) string +} + // TableName returns the corresponding name of the underlying database table // for a given `Model`. See also `TableNameAble` to change the default name of the table. func (m *Model) TableName() string { if s, ok := m.Value.(string); ok { return s } + if n, ok := m.Value.(TableNameAble); ok { return n.TableName() } - if m.tableName != "" { - return m.tableName + if n, ok := m.Value.(TableNameAbleWithContext); ok { + if m.ctx == nil { + m.ctx = context.TODO() + } + return n.TableName(m.ctx) } - t := reflect.TypeOf(m.Value) - name, cacheKey := m.typeName(t) - - defer tableMapMu.Unlock() - tableMapMu.Lock() - - if tableMap[cacheKey] == "" { - m.tableName = nflect.Tableize(name) - tableMap[cacheKey] = m.tableName - } - return tableMap[cacheKey] + return m.typeName(reflect.TypeOf(m.Value)) } func (m *Model) Columns() columns.Columns { @@ -121,7 +127,7 @@ func (m *Model) cacheKey(t reflect.Type) string { return t.PkgPath() + "." + t.Name() } -func (m *Model) typeName(t reflect.Type) (name, cacheKey string) { +func (m *Model) typeName(t reflect.Type) (name string) { if t.Kind() == reflect.Ptr { t = t.Elem() } @@ -133,19 +139,27 @@ func (m *Model) typeName(t reflect.Type) (name, cacheKey string) { } // validates if the elem of slice or array implements TableNameAble interface. - tableNameAble := (*TableNameAble)(nil) + var tableNameAble *TableNameAble if el.Implements(reflect.TypeOf(tableNameAble).Elem()) { v := reflect.New(el) out := v.MethodByName("TableName").Call([]reflect.Value{}) - name := out[0].String() - if tableMap[m.cacheKey(el)] == "" { - tableMap[m.cacheKey(el)] = name - } + return out[0].String() + } + + // validates if the elem of slice or array implements TableNameAbleWithContext interface. + var tableNameAbleWithContext *TableNameAbleWithContext + if el.Implements(reflect.TypeOf(tableNameAbleWithContext).Elem()) { + v := reflect.New(el) + out := v.MethodByName("TableName").Call([]reflect.Value{reflect.ValueOf(m.ctx)}) + return out[0].String() + + // We do not want to cache contextualized TableNames because that would break + // the contextualization. } - return el.Name(), m.cacheKey(el) + return nflect.Tableize(el.Name()) default: - return t.Name(), m.cacheKey(t) + return nflect.Tableize(t.Name()) } } @@ -209,11 +223,21 @@ func (m *Model) touchUpdatedAt() { } func (m *Model) whereID() string { - return fmt.Sprintf("%s.%s = ?", m.TableName(), m.IDField()) + as := m.As + if as == "" { + as = strings.ReplaceAll(m.TableName(), ".", "_") + } + + return fmt.Sprintf("%s.%s = ?", as, m.IDField()) } func (m *Model) whereNamedID() string { - return fmt.Sprintf("%s.%s = :%s", m.TableName(), m.IDField(), m.IDField()) + as := m.As + if as == "" { + as = strings.ReplaceAll(m.TableName(), ".", "_") + } + + return fmt.Sprintf("%s.%s = :%s", as, m.IDField(), m.IDField()) } func (m *Model) isSlice() bool { @@ -226,7 +250,10 @@ func (m *Model) iterate(fn modelIterable) error { v := reflect.Indirect(reflect.ValueOf(m.Value)) for i := 0; i < v.Len(); i++ { val := v.Index(i) - newModel := &Model{Value: val.Addr().Interface()} + newModel := &Model{ + Value: val.Addr().Interface(), + ctx: m.ctx, + } err := fn(newModel) if err != nil { diff --git a/model_context_test.go b/model_context_test.go new file mode 100644 index 00000000..6b03a882 --- /dev/null +++ b/model_context_test.go @@ -0,0 +1,109 @@ +package pop + +import ( + "context" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +type ContextTable struct { + ID string `db:"id"` + Value string `db:"value"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` +} + +func (t ContextTable) TableName(ctx context.Context) string { + // This is singular on purpose! It will checck if the TableName is properly + // Respected in slices as well. + return "context_prefix_" + ctx.Value("prefix").(string) + "_table" +} + +func Test_ModelContext(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + + t.Run("contextless", func(t *testing.T) { + r := require.New(t) + r.Panics(func() { + var c ContextTable + r.NoError(PDB.Create(&c)) + }, "panics if context prefix is not set") + }) + + for _, prefix := range []string{"a", "b"} { + t.Run("prefix="+prefix, func(t *testing.T) { + r := require.New(t) + + expected := ContextTable{ID: prefix, Value: prefix} + c := PDB.WithContext(context.WithValue(context.Background(), "prefix", prefix)) + r.NoError(c.Create(&expected)) + + var actual ContextTable + r.NoError(c.Find(&actual, expected.ID)) + r.EqualValues(prefix, actual.Value) + r.EqualValues(prefix, actual.ID) + + exists, err := c.Where("id = ?", actual.ID).Exists(new(ContextTable)) + r.NoError(err) + r.True(exists) + + count, err := c.Where("id = ?", actual.ID).Count(new(ContextTable)) + r.NoError(err) + r.EqualValues(1, count) + + expected.Value += expected.Value + r.NoError(c.Update(&expected)) + + r.NoError(c.Find(&actual, expected.ID)) + r.EqualValues(prefix+prefix, actual.Value) + r.EqualValues(prefix, actual.ID) + + var results []ContextTable + require.NoError(t, c.All(&results)) + + require.NoError(t, c.First(&expected)) + require.NoError(t, c.Last(&expected)) + + r.NoError(c.Destroy(&expected)) + }) + } + + t.Run("prefix=unknown", func(t *testing.T) { + r := require.New(t) + c := PDB.WithContext(context.WithValue(context.Background(), "prefix", "unknown")) + err := c.Create(&ContextTable{ID: "unknown"}) + r.Error(err) + + if !strings.Contains(err.Error(), "context_prefix_unknown_table") { // All other databases + t.Fatalf("Expected error to contain indicator that table does not exist but got: %s", err.Error()) + } + }) + + t.Run("cache_busting", func(t *testing.T) { + r := require.New(t) + + var expectedA, expectedB ContextTable + expectedA.ID = "expectedA" + expectedB.ID = "expectedB" + + cA := PDB.WithContext(context.WithValue(context.Background(), "prefix", "a")) + r.NoError(cA.Create(&expectedA)) + + cB := PDB.WithContext(context.WithValue(context.Background(), "prefix", "b")) + r.NoError(cB.Create(&expectedB)) + + var actualA, actualB []ContextTable + r.NoError(cA.All(&actualA)) + r.NoError(cB.All(&actualB)) + + r.Len(actualA, 1) + r.Len(actualB, 1) + + r.NotEqual(actualA[0].ID, actualB[0].ID, "if these are equal context switching did not work") + }) +} diff --git a/model_test.go b/model_test.go index 545eb09e..d0d0c23c 100644 --- a/model_test.go +++ b/model_test.go @@ -1,9 +1,14 @@ package pop import ( + "context" + "fmt" "testing" "time" + "github.com/gobuffalo/pop/v5/testdata/models/ac" + "github.com/gobuffalo/pop/v5/testdata/models/bc" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -12,26 +17,25 @@ import ( ) func Test_Model_TableName(t *testing.T) { - r := require.New(t) - - m := Model{Value: User{}} - r.Equal(m.TableName(), "users") - - m = Model{Value: &User{}} - r.Equal(m.TableName(), "users") - - m = Model{Value: &Users{}} - r.Equal(m.TableName(), "users") - - m = Model{Value: []User{}} - r.Equal(m.TableName(), "users") - - m = Model{Value: &[]User{}} - r.Equal(m.TableName(), "users") - - m = Model{Value: []*User{}} - r.Equal(m.TableName(), "users") - + for k, v := range []interface{}{ + User{}, + &User{}, + + &Users{}, + Users{}, + + []*User{}, + &[]*User{}, + + []User{}, + &[]User{}, + } { + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + r := require.New(t) + m := Model{Value: v} + r.Equal("users", m.TableName()) + }) + } } type tn struct{} @@ -40,6 +44,12 @@ func (tn) TableName() string { return "this is my table name" } +type tnc struct{} + +func (tnc) TableName(ctx context.Context) string { + return ctx.Value("name").(string) +} + // A failing test case for #477 func Test_TableNameCache(t *testing.T) { r := assert.New(t) @@ -49,12 +59,27 @@ func Test_TableNameCache(t *testing.T) { r.Equal("userb", (&Model{Value: []b.User{}}).TableName()) } +// A failing test case for #477 +func Test_TableNameContextCache(t *testing.T) { + ctx := context.WithValue(context.Background(), "name", "context_table") + + r := assert.New(t) + r.Equal("context_table_useras", (&Model{Value: ac.User{}, ctx: ctx}).TableName()) + r.Equal("context_table_userbs", (&Model{Value: bc.User{}, ctx: ctx}).TableName()) + r.Equal("context_table_useras", (&Model{Value: []ac.User{}, ctx: ctx}).TableName()) + r.Equal("context_table_userbs", (&Model{Value: []bc.User{}, ctx: ctx}).TableName()) +} + func Test_TableName(t *testing.T) { r := require.New(t) cases := []interface{}{ tn{}, + &tn{}, []tn{}, + &[]tn{}, + []*tn{}, + &[]*tn{}, } for _, tc := range cases { m := Model{Value: tc} @@ -62,6 +87,22 @@ func Test_TableName(t *testing.T) { } } +func Test_TableNameContext(t *testing.T) { + r := require.New(t) + + tn := "context_table_names" + ctx := context.WithValue(context.Background(), "name", tn) + + cases := []interface{}{ + tnc{}, + []tnc{}, + } + for _, tc := range cases { + m := Model{Value: tc, ctx: ctx} + r.Equal(tn, m.TableName()) + } +} + type TimeTimestamp struct { ID int `db:"id"` CreatedAt time.Time `db:"created_at"` @@ -77,7 +118,7 @@ type UnixTimestamp struct { func Test_Touch_Time_Timestamp(t *testing.T) { r := require.New(t) - m := Model{Value: &TimeTimestamp{}} + m := NewModel(&TimeTimestamp{}, context.Background()) // Override time.Now() t0, _ := time.Parse(time.RFC3339, "2019-07-14T00:00:00Z") @@ -101,7 +142,7 @@ func Test_Touch_Time_Timestamp_With_Existing_Value(t *testing.T) { createdAt := nowFunc().Add(-36 * time.Hour) - m := Model{Value: &TimeTimestamp{CreatedAt: createdAt}} + m := NewModel(&TimeTimestamp{CreatedAt: createdAt}, context.Background()) m.touchCreatedAt() m.touchUpdatedAt() v := m.Value.(*TimeTimestamp) @@ -112,7 +153,7 @@ func Test_Touch_Time_Timestamp_With_Existing_Value(t *testing.T) { func Test_Touch_Unix_Timestamp(t *testing.T) { r := require.New(t) - m := Model{Value: &UnixTimestamp{}} + m := NewModel(&UnixTimestamp{}, context.Background()) // Override time.Now() t0, _ := time.Parse(time.RFC3339, "2019-07-14T00:00:00Z") @@ -136,7 +177,7 @@ func Test_Touch_Unix_Timestamp_With_Existing_Value(t *testing.T) { createdAt := int(time.Now().Add(-36 * time.Hour).Unix()) - m := Model{Value: &UnixTimestamp{CreatedAt: createdAt}} + m := NewModel(&UnixTimestamp{CreatedAt: createdAt}, context.Background()) m.touchCreatedAt() m.touchUpdatedAt() v := m.Value.(*UnixTimestamp) @@ -159,3 +200,25 @@ func Test_IDField(t *testing.T) { m = Model{Value: &testNormalID{ID: 1}} r.Equal("id", m.IDField()) } + +type testPrefixID struct { + ID int `db:"custom_id"` +} + +func (t testPrefixID) TableName() string { + return "foo.bar" +} + +func Test_WhereID(t *testing.T) { + r := require.New(t) + m := Model{Value: &testPrefixID{ID: 1}} + + r.Equal("foo_bar.custom_id = ?", m.whereID()) + r.Equal("foo_bar.custom_id = :custom_id", m.whereNamedID()) + + type testNormalID struct { + ID int + } + m = Model{Value: &testNormalID{ID: 1}} + r.Equal("id", m.IDField()) +} diff --git a/preload_associations.go b/preload_associations.go index 8ddea3c9..c7c8b6c5 100644 --- a/preload_associations.go +++ b/preload_associations.go @@ -167,7 +167,7 @@ func (ami *AssociationMetaInfo) fkName() string { // preload is the query mode used to load associations from database // similar to the active record default approach on Rails. func preload(tx *Connection, model interface{}, fields ...string) error { - mmi := NewModelMetaInfo(&Model{Value: model}) + mmi := NewModelMetaInfo(NewModel(model, tx.Context())) preloadFields, err := mmi.preloadFields(fields...) if err != nil { diff --git a/query_test.go b/query_test.go index 93da765c..7df5a994 100644 --- a/query_test.go +++ b/query_test.go @@ -1,6 +1,7 @@ package pop import ( + "context" "fmt" "testing" @@ -13,7 +14,7 @@ func Test_Where(t *testing.T) { t.Skip("skipping integration tests") } a := require.New(t) - m := &Model{Value: &Enemy{}} + m := NewModel(new(Enemy), context.Background()) q := PDB.Where("id = ?", 1) sql, _ := q.ToSQL(m) @@ -107,7 +108,7 @@ func Test_Order(t *testing.T) { } a := require.New(t) - m := &Model{Value: &Enemy{}} + m := NewModel(&Enemy{}, context.Background()) q := PDB.Order("id desc") sql, _ := q.ToSQL(m) a.Equal(ts("SELECT enemies.A FROM enemies AS enemies ORDER BY id desc"), sql) @@ -123,7 +124,7 @@ func Test_GroupBy(t *testing.T) { } a := require.New(t) - m := &Model{Value: &Enemy{}} + m := NewModel(&Enemy{}, context.Background()) q := PDB.Q() q.GroupBy("A") sql, _ := q.ToSQL(m) @@ -159,7 +160,7 @@ func Test_ToSQL(t *testing.T) { } a := require.New(t) transaction(func(tx *Connection) { - user := &Model{Value: &User{}} + user := NewModel(&User{}, tx.Context()) s := "SELECT name as full_name, users.alive, users.bio, users.birth_date, users.created_at, users.email, users.id, users.name, users.price, users.updated_at, users.user_name FROM users AS users" @@ -171,10 +172,10 @@ func Test_ToSQL(t *testing.T) { q, _ = query.ToSQL(user) a.Equal(fmt.Sprintf("%s ORDER BY id desc", s), q) - q, _ = query.ToSQL(&Model{Value: &User{}, As: "u"}) + q, _ = query.ToSQL(&Model{Value: &User{}, As: "u", ctx: tx.Context()}) a.Equal("SELECT name as full_name, u.alive, u.bio, u.birth_date, u.created_at, u.email, u.id, u.name, u.price, u.updated_at, u.user_name FROM users AS u ORDER BY id desc", q) - q, _ = query.ToSQL(&Model{Value: &Family{}}) + q, _ = query.ToSQL(&Model{Value: &Family{}, ctx: tx.Context()}) a.Equal("SELECT family_members.created_at, family_members.first_name, family_members.id, family_members.last_name, family_members.updated_at FROM family.members AS family_members ORDER BY id desc", q) query = tx.Where("id = 1") @@ -262,7 +263,7 @@ func Test_ToSQLInjection(t *testing.T) { } a := require.New(t) transaction(func(tx *Connection) { - user := &Model{Value: &User{}} + user := NewModel(new(User), tx.Context()) query := tx.Where("name = '?'", "\\\u0027 or 1=1 limit 1;\n-- ") q, _ := query.ToSQL(user) a.NotEqual("SELECT * FROM users AS users WHERE name = '\\'' or 1=1 limit 1;\n-- '", q) diff --git a/scopes_test.go b/scopes_test.go index 0e22b76e..f393ffb3 100644 --- a/scopes_test.go +++ b/scopes_test.go @@ -1,6 +1,7 @@ package pop import ( + "context" "testing" "github.com/stretchr/testify/require" @@ -13,7 +14,7 @@ func Test_Scopes(t *testing.T) { r := require.New(t) oql := "SELECT enemies.A FROM enemies AS enemies" - m := &Model{Value: &Enemy{}} + m := NewModel(new(Enemy), context.Background()) q := PDB.Q() s, _ := q.ToSQL(m) diff --git a/soda/cmd/migrate_status.go b/soda/cmd/migrate_status.go index e9a85df6..98d0aae4 100644 --- a/soda/cmd/migrate_status.go +++ b/soda/cmd/migrate_status.go @@ -1,9 +1,10 @@ package cmd import ( + "os" + "github.com/gobuffalo/pop/v5" "github.com/spf13/cobra" - "os" ) var migrateStatusCmd = &cobra.Command{ diff --git a/store.go b/store.go index cc98a266..39c554ed 100644 --- a/store.go +++ b/store.go @@ -54,3 +54,7 @@ func (s contextStore) Exec(query string, args ...interface{}) (sql.Result, error func (s contextStore) PrepareNamed(query string) (*sqlx.NamedStmt, error) { return s.store.PrepareNamedContext(s.ctx, query) } + +func (s contextStore) Context() context.Context { + return s.ctx +} diff --git a/testdata/migrations/20210104145901_context_tables.down.fizz b/testdata/migrations/20210104145901_context_tables.down.fizz new file mode 100644 index 00000000..d0f82ee2 --- /dev/null +++ b/testdata/migrations/20210104145901_context_tables.down.fizz @@ -0,0 +1,2 @@ +drop_table("context_prefix_a_table") +drop_table("context_prefix_b_table") diff --git a/testdata/migrations/20210104145901_context_tables.up.fizz b/testdata/migrations/20210104145901_context_tables.up.fizz new file mode 100644 index 00000000..ae94796f --- /dev/null +++ b/testdata/migrations/20210104145901_context_tables.up.fizz @@ -0,0 +1,9 @@ +create_table("context_prefix_a_table") { + t.Column("id", "string", { primary: true }) + t.Column("value", "string") +} + +create_table("context_prefix_b_table") { + t.Column("id", "string", { primary: true }) + t.Column("value", "string") +} diff --git a/testdata/models/ac/user.go b/testdata/models/ac/user.go new file mode 100644 index 00000000..92335a16 --- /dev/null +++ b/testdata/models/ac/user.go @@ -0,0 +1,9 @@ +package ac + +import "context" + +type User struct{} + +func (u User) TableName(ctx context.Context) string { + return ctx.Value("name").(string) + "_useras" +} diff --git a/testdata/models/bc/user.go b/testdata/models/bc/user.go new file mode 100644 index 00000000..4b1c6257 --- /dev/null +++ b/testdata/models/bc/user.go @@ -0,0 +1,9 @@ +package bc + +import "context" + +type User struct{} + +func (u User) TableName(ctx context.Context) string { + return ctx.Value("name").(string) + "_userbs" +} diff --git a/validations.go b/validations.go index 79e76105..ab5b845e 100644 --- a/validations.go +++ b/validations.go @@ -133,7 +133,7 @@ func (m *Model) iterateAndValidate(fn modelIterableValidator) (*validate.Errors, if v.Kind() == reflect.Slice || v.Kind() == reflect.Array { for i := 0; i < v.Len(); i++ { val := v.Index(i) - newModel := &Model{Value: val.Addr().Interface()} + newModel := NewModel(val.Addr().Interface(), m.ctx) verrs, err := fn(newModel) if err != nil || verrs.HasAny() { From 119c0d2898c03e21ce4b36f3435002841913ad1a Mon Sep 17 00:00:00 2001 From: Antonio Pagano <645522+paganotoni@users.noreply.github.com> Date: Wed, 27 Jan 2021 15:33:50 -0500 Subject: [PATCH 07/59] Bump pg deps (#616) * Reset to development * bumping pgx and pgconn versions Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan --- go.mod | 4 +-- go.sum | 82 ++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 225a6ac6..346ac0ee 100644 --- a/go.mod +++ b/go.mod @@ -20,8 +20,8 @@ require ( github.com/gobuffalo/plush/v4 v4.0.0 github.com/gobuffalo/validate/v3 v3.1.0 github.com/gofrs/uuid v3.2.0+incompatible - github.com/jackc/pgconn v1.6.0 - github.com/jackc/pgx/v4 v4.6.0 + github.com/jackc/pgconn v1.8.0 + github.com/jackc/pgx/v4 v4.10.1 github.com/jmoiron/sqlx v1.2.0 github.com/karrick/godirwalk v1.16.1 // indirect github.com/lib/pq v1.3.0 diff --git a/go.sum b/go.sum index 22100ac4..e00ce20b 100644 --- a/go.sum +++ b/go.sum @@ -47,7 +47,6 @@ github.com/gobuffalo/envy v1.8.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6 github.com/gobuffalo/fizz v1.10.0 h1:I8vad0PnmR+CLjSnZ5L5jlhBm4S88UIGOoZZL3/3e24= github.com/gobuffalo/fizz v1.10.0/go.mod h1:J2XGPO0AfJ1zKw7+2BA+6FEGAkyEsdCOLvN93WCT2WI= github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= -github.com/gobuffalo/flect v0.2.0 h1:EWCvMGGxOjsgwlWaP+f4+Hh6yrrte7JeFL2S6b+0hdM= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gobuffalo/flect v0.2.1 h1:GPoRjEN0QObosV4XwuoWvSd5uSiL0N3e91/xqyY4crQ= github.com/gobuffalo/flect v0.2.1/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= @@ -55,7 +54,6 @@ github.com/gobuffalo/genny/v2 v2.0.5 h1:IH0EHcvwKT0MdASzptvkz/ViYBQELTklq1/l8Ot3 github.com/gobuffalo/genny/v2 v2.0.5/go.mod h1:kRkJuAw9mdI37AiEYjV4Dl+TgkBDYf8HZVjLkqe5eBg= github.com/gobuffalo/github_flavored_markdown v1.1.0 h1:8Zzj4fTRl/OP2R7sGerzSf6g2nEJnaBEJe7UAOiEvbQ= github.com/gobuffalo/github_flavored_markdown v1.1.0/go.mod h1:TSpTKWcRTI0+v7W3x8dkSKMLJSUpuVitlptCkpeY8ic= -github.com/gobuffalo/helpers v0.6.0 h1:CL1xOSGeKCaKD1IUpo4RfrkDU83kmkMG4H3dXAS7dw0= github.com/gobuffalo/helpers v0.6.0/go.mod h1:pncVrer7x/KRvnL5aJABLAuT/RhKRR9klL6dkUOhyv8= github.com/gobuffalo/helpers v0.6.1 h1:LLcL4BsiyDQYtMRUUpyFdBFvFXQ6hNYOpwrcYeilVWM= github.com/gobuffalo/helpers v0.6.1/go.mod h1:wInbDi0vTJKZBviURTLRMFLE4+nF2uRuuL2fnlYo7w4= @@ -63,7 +61,6 @@ github.com/gobuffalo/logger v1.0.3 h1:YaXOTHNPCvkqqA7w05A4v0k2tCdpr+sgFlgINbQ6gq github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM= github.com/gobuffalo/nulls v0.2.0 h1:7R0Uec6JlZI02TR29zrs3KFIuUV8Sqe/s/j3yLvs+gc= github.com/gobuffalo/nulls v0.2.0/go.mod h1:w4q8RoSCEt87Q0K0sRIZWYeIxkxog5mh3eN3C/n+dUc= -github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM= github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI= @@ -71,11 +68,9 @@ github.com/gobuffalo/packr/v2 v2.8.0 h1:IULGd15bQL59ijXLxEvA5wlMxsmx/ZkQv9T282zN github.com/gobuffalo/packr/v2 v2.8.0/go.mod h1:PDk2k3vGevNE3SwVyVRgQCCXETC9SaONCNSXT1Q8M1g= github.com/gobuffalo/plush/v4 v4.0.0 h1:ZHdmfr2R7DQ77XzWZK2PGKJOXm9NRy21EZ6Rw7FhuNw= github.com/gobuffalo/plush/v4 v4.0.0/go.mod h1:ErFS3UxKqEb8fpFJT7lYErfN/Nw6vHGiDMTjxpk5bQ0= -github.com/gobuffalo/tags/v3 v3.0.2 h1:gxE6c6fA5radwQeg59aPIeYgCG8YA8AZd3Oh6fh5UXA= github.com/gobuffalo/tags/v3 v3.0.2/go.mod h1:ZQeN6TCTiwAFnS0dNcbDtSgZDwNKSpqajvVtt6mlYpA= github.com/gobuffalo/tags/v3 v3.1.0 h1:mzdCYooN2VsLRr8KIAdEZ1lh1Py7JSMsiEGCGata2AQ= github.com/gobuffalo/tags/v3 v3.1.0/go.mod h1:ZQeN6TCTiwAFnS0dNcbDtSgZDwNKSpqajvVtt6mlYpA= -github.com/gobuffalo/validate/v3 v3.0.0 h1:dF7Bg8NMF9Zv8bZvUMXYJXxZdj+eSZ8z/lGM7/jVFUE= github.com/gobuffalo/validate/v3 v3.0.0/go.mod h1:HFpjq+AIiA2RHoQnQVTFKF/ZpUPXwyw82LgyDPxQ9r0= github.com/gobuffalo/validate/v3 v3.1.0 h1:/QQN920PciCfBs3aywtJTvDTHmBFMKoiwkshUWa/HLQ= github.com/gobuffalo/validate/v3 v3.1.0/go.mod h1:HFpjq+AIiA2RHoQnQVTFKF/ZpUPXwyw82LgyDPxQ9r0= @@ -90,6 +85,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -99,16 +95,17 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0 h1:DUwgMQuuPnS0rhMXenUtZpqZqrR/30NWY+qQvTpSvEs= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.6.0 h1:8FiBxMxS/Z0eQ9BeE1HhL6pzPL1R5x+ZuQ+T86WgZ4I= -github.com/jackc/pgconn v1.6.0/go.mod h1:yeseQo4xhQbgyJs2c87RAXOH2i624N0Fh1KSPJya7qo= +github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.8.0 h1:FmjZ0rOyXTr1wfWs45i4a9vjnjWUAGpMuQLD9OSs+lw= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA= @@ -121,36 +118,39 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1 h1:Rdjp4NFjwHnEslx2b66FfCI2S0LhO4itac3hXz6WX9M= github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY= -github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 h1:Q3tB+ExeflWUW7AFcAhXqk40s9mnNYLk1nOkKNZ5GnU= +github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59 h1:xOamcCJ9MFJTxR5bvw3ZXmiP8evQMohdt2VJ57C0W8Q= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.3.0 h1:l8JvKrby3RI7Kg3bYEeU9TA4vqC38QDpFCfcrC7KuN0= -github.com/jackc/pgtype v1.3.0/go.mod h1:b0JqxHvPmljG+HQ5IsvQ0yqeSi4nGcDTVjFoiLDb0Ik= -github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o= -github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= +github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= +github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= +github.com/jackc/pgtype v1.6.2 h1:b3pDeuhbbzBYcg5kwNmNDun4pFUD/0AAr1kLXZLeNt8= +github.com/jackc/pgtype v1.6.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186 h1:ZQM8qLT/E/CGD6XX0E6q9FAwxJYmWpJufzmLMaFuzgQ= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.6.0 h1:Fh0O9GdlG4gYpjpwOqjdEodJUQM9jzN3Hdv7PN0xmm0= -github.com/jackc/pgx/v4 v4.6.0/go.mod h1:vPh43ZzxijXUVJ+t/EmXBtFmbFVO72cuneCT9oAlxAg= +github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= +github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= +github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= +github.com/jackc/pgx/v4 v4.10.1 h1:/6Q3ye4myIj6AaplUm+eRcz4OhK9HAvFf4ePsG40LJY= +github.com/jackc/pgx/v4 v4.10.1/go.mod h1:QlrWebbs3kqEZPHCTGyxecvzG6tvIsYu+A5b1raylkA= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karrick/godirwalk v1.15.3 h1:0a2pXOgtB16CqIqXTiT7+K9L73f74n/aNQUnH6Ortew= github.com/karrick/godirwalk v1.15.3/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= @@ -162,7 +162,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -186,14 +185,16 @@ github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -220,6 +221,7 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.5.2 h1:qLvObTrvO/XRCqmkKxUlOBc48bI3efyDuAZe25QiF0w= github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -227,14 +229,13 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY= +github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -259,7 +260,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -271,20 +271,27 @@ github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxt go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c h1:/nJuwDLoL/zrqY6gf57vxC+Pi+pZ8bfhpPkicO5H7W4= golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -296,9 +303,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -322,29 +327,32 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9 h1:KOkk4e2xd5OeCDJGwacvr75ICCbCsShrHiqPEdsA9hg= golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200308013534-11ec41452d41 h1:9Di9iYgOt9ThCipBxChBVhgNipDoE5mxO84rQV7D0FE= golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -354,7 +362,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -368,3 +375,4 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= From f252caad58952e0bf59005f6ffca7cb601b403cd Mon Sep 17 00:00:00 2001 From: Antonio Pagano <645522+paganotoni@users.noreply.github.com> Date: Thu, 28 Jan 2021 15:28:00 -0500 Subject: [PATCH 08/59] Latest from master (#620) * Latest from development (#617) * fix: improve model ID field customization (#604) Updates places where `"id"` was hardcoded instead of using `model.IDField()`. * Ensure uninitialized map is initialized when unmarshaling json Add tests for this scenario * exclude migration_table_name from connection string * add test for OptionsString * Add support for pointer FKs when preloading a belongs_to association (#602) * feat: support context-aware tablenames (#614) This patch adds a feature which enables pop to pass down the connection context to the model's TableName() function by implementing TableName(ctx context.Context) string. The context can be used to dynamically generate tablenames which can be important for prefixed or generic tables and other use cases. * Bump pg deps (#616) * Reset to development * bumping pgx and pgconn versions Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * adding goreleaser syntaz (#619) Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan --- .goreleaser.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index c5f8224b..f22cfd3f 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -89,7 +89,8 @@ changelog: brews: - - github: + name: 'pop' + tap: owner: gobuffalo name: homebrew-tap homepage: "https://gobuffalo.io/docs/db/getting-started" From ad18e4dd8909aa26893cdc440115e5dbfe5630a0 Mon Sep 17 00:00:00 2001 From: hackerman <3372410+aeneasr@users.noreply.github.com> Date: Sat, 6 Feb 2021 09:29:33 +0100 Subject: [PATCH 09/59] Resolve issues in UPDATE and DELETE when using schemas (#618) * Resolve MySQL issues and improve test migrations * Bump CockroachDB to maintained and supported versions Version 2.1 has reached EoL in 2019 Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- .github/workflows/tests.yml | 12 +++--- dialect_cockroach.go | 2 +- dialect_common.go | 4 +- dialect_mysql.go | 4 +- dialect_postgresql.go | 2 +- docker-compose.yml | 5 +-- model.go | 14 +++---- model_context_test.go | 22 +++++++++-- sql_builder.go | 10 +---- .../20210104145901_context_tables.up.fizz | 39 ++++++++++++++----- 10 files changed, 72 insertions(+), 42 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e762954c..4b1b3129 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -110,12 +110,12 @@ jobs: run: | mkdir -p crdb/certs pushd crdb - wget -qO- https://binaries.cockroachdb.com/cockroach-v2.1.0.linux-amd64.tgz | tar zxv - mv cockroach-v2.1.0.linux-amd64/cockroach . + wget -qO- https://binaries.cockroachdb.com/cockroach-v20.2.4.linux-amd64.tgz | tar zxv + mv cockroach-v20.2.4.linux-amd64/cockroach . ./cockroach cert create-ca --certs-dir certs --ca-key key ./cockroach cert create-client root --certs-dir certs --ca-key key ./cockroach cert create-node localhost 127.0.0.1 `hostname -s` `hostname -f` --certs-dir certs --ca-key key - ./cockroach start --certs-dir certs --listen-addr localhost --port 26259 --http-port 8089 --background + ./cockroach start-single-node --certs-dir certs --listen-addr localhost --port 26259 --http-port 8089 --background popd - name: Build and run soda env: @@ -152,9 +152,9 @@ jobs: run: | mkdir -p crdb pushd crdb - wget -qO- https://binaries.cockroachdb.com/cockroach-v2.1.0.linux-amd64.tgz | tar zxv - mv cockroach-v2.1.0.linux-amd64/cockroach . - ./cockroach start --insecure --background + wget -qO- https://binaries.cockroachdb.com/cockroach-v20.2.4.linux-amd64.tgz | tar zxv + mv cockroach-v20.2.4.linux-amd64/cockroach . + ./cockroach start-single-node --insecure --background popd - name: Build and run soda env: diff --git a/dialect_cockroach.go b/dialect_cockroach.go index 61094765..cab020a5 100644 --- a/dialect_cockroach.go +++ b/dialect_cockroach.go @@ -105,7 +105,7 @@ func (p *cockroach) Update(s store, model *Model, cols columns.Columns) error { } func (p *cockroach) Destroy(s store, model *Model) error { - stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s WHERE %s", p.Quote(model.TableName()), model.whereID())) + stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", p.Quote(model.TableName()), model.alias(), model.whereID())) _, err := genericExec(s, stmt, model.ID()) return err } diff --git a/dialect_common.go b/dialect_common.go index b34caae8..7da27adb 100644 --- a/dialect_common.go +++ b/dialect_common.go @@ -99,7 +99,7 @@ func genericCreate(s store, model *Model, cols columns.Columns, quoter quotable) } func genericUpdate(s store, model *Model, cols columns.Columns, quoter quotable) error { - stmt := fmt.Sprintf("UPDATE %s SET %s WHERE %s", quoter.Quote(model.TableName()), cols.Writeable().QuotedUpdateString(quoter), model.whereNamedID()) + stmt := fmt.Sprintf("UPDATE %s AS %s SET %s WHERE %s", quoter.Quote(model.TableName()), model.alias(), cols.Writeable().QuotedUpdateString(quoter), model.whereNamedID()) log(logging.SQL, stmt, model.ID()) _, err := s.NamedExec(stmt, model.Value) if err != nil { @@ -109,7 +109,7 @@ func genericUpdate(s store, model *Model, cols columns.Columns, quoter quotable) } func genericDestroy(s store, model *Model, quoter quotable) error { - stmt := fmt.Sprintf("DELETE FROM %s WHERE %s", quoter.Quote(model.TableName()), model.whereID()) + stmt := fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", quoter.Quote(model.TableName()), model.alias(), model.whereID()) _, err := genericExec(s, stmt, model.ID()) if err != nil { return err diff --git a/dialect_mysql.go b/dialect_mysql.go index 63fb9006..5dda6f5d 100644 --- a/dialect_mysql.go +++ b/dialect_mysql.go @@ -91,7 +91,9 @@ func (m *mysql) Update(s store, model *Model, cols columns.Columns) error { } func (m *mysql) Destroy(s store, model *Model) error { - return errors.Wrap(genericDestroy(s, model, m), "mysql destroy") + stmt := fmt.Sprintf("DELETE FROM %s WHERE %s = ?", m.Quote(model.TableName()), model.IDField()) + _, err := genericExec(s, stmt, model.ID()) + return errors.Wrap(err, "mysql destroy") } func (m *mysql) SelectOne(s store, model *Model, query Query) error { diff --git a/dialect_postgresql.go b/dialect_postgresql.go index 3409d4ba..ccb8e43d 100644 --- a/dialect_postgresql.go +++ b/dialect_postgresql.go @@ -92,7 +92,7 @@ func (p *postgresql) Update(s store, model *Model, cols columns.Columns) error { } func (p *postgresql) Destroy(s store, model *Model) error { - stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s WHERE %s", p.Quote(model.TableName()), model.whereID())) + stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", p.Quote(model.TableName()), model.alias(), model.whereID())) _, err := genericExec(s, stmt, model.ID()) if err != nil { return err diff --git a/docker-compose.yml b/docker-compose.yml index b49afad1..6c058cc8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,10 +24,9 @@ services: volumes: - ./sqldumps:/docker-entrypoint-initdb.d cockroach: - image: cockroachdb/cockroach:v2.1.0 + image: cockroachdb/cockroach:v20.2.4 ports: - "26257:26257" - - "8080:8080" volumes: - "./cockroach-data/roach1:/cockroach/cockroach-data" - command: start --insecure + command: start-single-node --insecure diff --git a/model.go b/model.go index 1dea97f5..2b20dace 100644 --- a/model.go +++ b/model.go @@ -223,21 +223,19 @@ func (m *Model) touchUpdatedAt() { } func (m *Model) whereID() string { - as := m.As - if as == "" { - as = strings.ReplaceAll(m.TableName(), ".", "_") - } - - return fmt.Sprintf("%s.%s = ?", as, m.IDField()) + return fmt.Sprintf("%s.%s = ?", m.alias(), m.IDField()) } -func (m *Model) whereNamedID() string { +func (m *Model) alias() string { as := m.As if as == "" { as = strings.ReplaceAll(m.TableName(), ".", "_") } + return as +} - return fmt.Sprintf("%s.%s = :%s", as, m.IDField(), m.IDField()) +func (m *Model) whereNamedID() string { + return fmt.Sprintf("%s.%s = :%s", m.alias(), m.IDField(), m.IDField()) } func (m *Model) isSlice() bool { diff --git a/model_context_test.go b/model_context_test.go index 6b03a882..0e8c2977 100644 --- a/model_context_test.go +++ b/model_context_test.go @@ -17,9 +17,24 @@ type ContextTable struct { } func (t ContextTable) TableName(ctx context.Context) string { - // This is singular on purpose! It will checck if the TableName is properly + // This is singular on purpose! It will check if the TableName is properly // Respected in slices as well. - return "context_prefix_" + ctx.Value("prefix").(string) + "_table" + prefix := ctx.Value("prefix").(string) + + // PostgreSQL and CockroachDB support schemas which work like a prefix. For those cases, we use + // the schema to ensure that name normalization does not cause query problems. + // + // Since this works only for those two databases, we use underscore for the rest. + // + // While this schema is hardcoded, it would have been too difficult to add this special + // case to the migrations. + switch PDB.Dialect.Name() { + case nameCockroach: + fallthrough + case namePostgreSQL: + prefix = prefix + "." + prefix + } + return "context_prefix_" + prefix + "_table" } func Test_ModelContext(t *testing.T) { @@ -41,6 +56,7 @@ func Test_ModelContext(t *testing.T) { expected := ContextTable{ID: prefix, Value: prefix} c := PDB.WithContext(context.WithValue(context.Background(), "prefix", prefix)) + r.NoError(c.Create(&expected)) var actual ContextTable @@ -79,7 +95,7 @@ func Test_ModelContext(t *testing.T) { err := c.Create(&ContextTable{ID: "unknown"}) r.Error(err) - if !strings.Contains(err.Error(), "context_prefix_unknown_table") { // All other databases + if !strings.Contains(err.Error(), "context_prefix_unknown") { // All other databases t.Fatalf("Expected error to contain indicator that table does not exist but got: %s", err.Error()) } }) diff --git a/sql_builder.go b/sql_builder.go index edd05c46..44820f4e 100644 --- a/sql_builder.go +++ b/sql_builder.go @@ -125,10 +125,7 @@ func (sq *sqlBuilder) buildfromClauses() fromClauses { fc := sq.Query.fromClauses for _, m := range models { tableName := m.TableName() - asName := m.As - if asName == "" { - asName = strings.Replace(tableName, ".", "_", -1) - } + asName := m.alias() fc = append(fc, fromClause{ From: tableName, As: asName, @@ -216,10 +213,7 @@ var columnCacheMutex = sync.RWMutex{} func (sq *sqlBuilder) buildColumns() columns.Columns { tableName := sq.Model.TableName() - asName := sq.Model.As - if asName == "" { - asName = strings.Replace(tableName, ".", "_", -1) - } + asName := sq.Model.alias() acl := len(sq.AddColumns) if acl == 0 { columnCacheMutex.RLock() diff --git a/testdata/migrations/20210104145901_context_tables.up.fizz b/testdata/migrations/20210104145901_context_tables.up.fizz index ae94796f..13c6a35a 100644 --- a/testdata/migrations/20210104145901_context_tables.up.fizz +++ b/testdata/migrations/20210104145901_context_tables.up.fizz @@ -1,9 +1,30 @@ -create_table("context_prefix_a_table") { - t.Column("id", "string", { primary: true }) - t.Column("value", "string") -} - -create_table("context_prefix_b_table") { - t.Column("id", "string", { primary: true }) - t.Column("value", "string") -} +{{ if eq .Dialect "sqlite3" }} + create_table("context_prefix_a_table") { + t.Column("id", "string", { primary: true }) + t.Column("value", "string") + } + + create_table("context_prefix_b_table") { + t.Column("id", "string", { primary: true }) + t.Column("value", "string") + } +{{ end }} + +{{ if eq .Dialect "mysql" }} + create_table("context_prefix_a_table") { + t.Column("id", "string", { primary: true }) + t.Column("value", "string") + } + + create_table("context_prefix_b_table") { + t.Column("id", "string", { primary: true }) + t.Column("value", "string") + } +{{ end }} + +{{ if eq .Dialect "postgres" }} + sql("CREATE SCHEMA IF NOT EXISTS \"context_prefix_a\";COMMIT TRANSACTION;BEGIN TRANSACTION;") + sql("CREATE SCHEMA IF NOT EXISTS \"context_prefix_b\";COMMIT TRANSACTION;BEGIN TRANSACTION;") + sql("CREATE TABLE \"context_prefix_a\".\"a_table\" (id character varying(255) NOT NULL, value character varying(255) NOT NULL, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL);COMMIT TRANSACTION;BEGIN TRANSACTION;") + sql("CREATE TABLE \"context_prefix_b\".\"b_table\" (id character varying(255) NOT NULL, value character varying(255) NOT NULL, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL);COMMIT TRANSACTION;BEGIN TRANSACTION;") +{{ end }} From e314840630d2597765e66d8944642648c074ea9a Mon Sep 17 00:00:00 2001 From: Brian Buchholz <4773480+bhb603@users.noreply.github.com> Date: Sat, 6 Feb 2021 03:39:19 -0500 Subject: [PATCH 10/59] Use `PaginatorPageKey` and `PaginatorPerPageKey` variables (#615) * update pagination_test --- pagination_test.go | 4 ++-- paginator.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pagination_test.go b/pagination_test.go index 08811420..f8284b8c 100644 --- a/pagination_test.go +++ b/pagination_test.go @@ -31,12 +31,12 @@ func Test_NewPaginatorFromParams(t *testing.T) { a.Equal(p.Page, 1) a.Equal(p.PerPage, 20) - params.Set("page", "2") + params.Set(PaginatorPageKey, "2") p = NewPaginatorFromParams(params) a.Equal(p.Page, 2) a.Equal(p.PerPage, 20) - params.Set("per_page", "30") + params.Set(PaginatorPerPageKey, "30") p = NewPaginatorFromParams(params) a.Equal(p.Page, 2) a.Equal(p.PerPage, 30) diff --git a/paginator.go b/paginator.go index 1a2f3dd2..1da4d438 100644 --- a/paginator.go +++ b/paginator.go @@ -75,9 +75,9 @@ type PaginationParams interface { // `PaginatorPerPageKey`. Defaults are `1` for the page and // PaginatorPerPageDefault for the per page value. func NewPaginatorFromParams(params PaginationParams) *Paginator { - page := defaults.String(params.Get("page"), "1") + page := defaults.String(params.Get(PaginatorPageKey), "1") - perPage := defaults.String(params.Get("per_page"), strconv.Itoa(PaginatorPerPageDefault)) + perPage := defaults.String(params.Get(PaginatorPerPageKey), strconv.Itoa(PaginatorPerPageDefault)) p, err := strconv.Atoi(page) if err != nil { From 46cfd45aeaac93ff2912abe5b7030e7a35510dd5 Mon Sep 17 00:00:00 2001 From: Mike Pontillo Date: Sun, 7 Mar 2021 22:45:52 -0800 Subject: [PATCH 11/59] Pass Time structure into timestamp update functions. (#625) Closes #624 --- executors.go | 12 ++++++++---- model.go | 6 ++---- model_test.go | 24 ++++++++---------------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/executors.go b/executors.go index 657ecea7..c382f260 100644 --- a/executors.go +++ b/executors.go @@ -2,6 +2,7 @@ package pop import ( "reflect" + "time" "github.com/gobuffalo/pop/v5/associations" "github.com/gobuffalo/pop/v5/columns" @@ -234,8 +235,9 @@ func (c *Connection) Create(model interface{}, excludeColumns ...string) error { cols.Remove(excludeColumns...) } - m.touchCreatedAt() - m.touchUpdatedAt() + now := nowFunc().Truncate(time.Microsecond) + m.setUpdatedAt(now) + m.setCreatedAt(now) if err = c.Dialect.Create(c.Store, m, cols); err != nil { return err @@ -357,7 +359,8 @@ func (c *Connection) Update(model interface{}, excludeColumns ...string) error { cols.Remove(excludeColumns...) } - m.touchUpdatedAt() + now := nowFunc().Truncate(time.Microsecond) + m.setUpdatedAt(now) if err = c.Dialect.Update(c.Store, m, cols); err != nil { return err @@ -401,7 +404,8 @@ func (c *Connection) UpdateColumns(model interface{}, columnNames ...string) err } cols.Remove("id", "created_at") - m.touchUpdatedAt() + now := nowFunc().Truncate(time.Microsecond) + m.setUpdatedAt(now) if err = c.Dialect.Update(c.Store, m, cols); err != nil { return err diff --git a/model.go b/model.go index 2b20dace..8b47e1be 100644 --- a/model.go +++ b/model.go @@ -190,10 +190,9 @@ func (m *Model) setID(i interface{}) { } } -func (m *Model) touchCreatedAt() { +func (m *Model) setCreatedAt(now time.Time) { fbn, err := m.fieldByName("CreatedAt") if err == nil { - now := nowFunc().Truncate(time.Microsecond) v := fbn.Interface() if !IsZeroOfUnderlyingType(v) { // Do not override already set CreatedAt @@ -208,10 +207,9 @@ func (m *Model) touchCreatedAt() { } } -func (m *Model) touchUpdatedAt() { +func (m *Model) setUpdatedAt(now time.Time) { fbn, err := m.fieldByName("UpdatedAt") if err == nil { - now := nowFunc().Truncate(time.Microsecond) v := fbn.Interface() switch v.(type) { case int, int64: diff --git a/model_test.go b/model_test.go index d0d0c23c..13a376fa 100644 --- a/model_test.go +++ b/model_test.go @@ -122,11 +122,9 @@ func Test_Touch_Time_Timestamp(t *testing.T) { // Override time.Now() t0, _ := time.Parse(time.RFC3339, "2019-07-14T00:00:00Z") - nowFunc = func() time.Time { return t0 } - defer func() { nowFunc = time.Now }() - m.touchCreatedAt() - m.touchUpdatedAt() + m.setCreatedAt(t0) + m.setUpdatedAt(t0) v := m.Value.(*TimeTimestamp) r.Equal(t0, v.CreatedAt) r.Equal(t0, v.UpdatedAt) @@ -137,14 +135,12 @@ func Test_Touch_Time_Timestamp_With_Existing_Value(t *testing.T) { // Override time.Now() t0, _ := time.Parse(time.RFC3339, "2019-07-14T00:00:00Z") - nowFunc = func() time.Time { return t0 } - defer func() { nowFunc = time.Now }() createdAt := nowFunc().Add(-36 * time.Hour) m := NewModel(&TimeTimestamp{CreatedAt: createdAt}, context.Background()) - m.touchCreatedAt() - m.touchUpdatedAt() + m.setCreatedAt(t0) + m.setUpdatedAt(t0) v := m.Value.(*TimeTimestamp) r.Equal(createdAt, v.CreatedAt) r.Equal(t0, v.UpdatedAt) @@ -157,11 +153,9 @@ func Test_Touch_Unix_Timestamp(t *testing.T) { // Override time.Now() t0, _ := time.Parse(time.RFC3339, "2019-07-14T00:00:00Z") - nowFunc = func() time.Time { return t0 } - defer func() { nowFunc = time.Now }() - m.touchCreatedAt() - m.touchUpdatedAt() + m.setCreatedAt(t0) + m.setUpdatedAt(t0) v := m.Value.(*UnixTimestamp) r.Equal(int(t0.Unix()), v.CreatedAt) r.Equal(int(t0.Unix()), v.UpdatedAt) @@ -172,14 +166,12 @@ func Test_Touch_Unix_Timestamp_With_Existing_Value(t *testing.T) { // Override time.Now() t0, _ := time.Parse(time.RFC3339, "2019-07-14T00:00:00Z") - nowFunc = func() time.Time { return t0 } - defer func() { nowFunc = time.Now }() createdAt := int(time.Now().Add(-36 * time.Hour).Unix()) m := NewModel(&UnixTimestamp{CreatedAt: createdAt}, context.Background()) - m.touchCreatedAt() - m.touchUpdatedAt() + m.setCreatedAt(t0) + m.setUpdatedAt(t0) v := m.Value.(*UnixTimestamp) r.Equal(createdAt, v.CreatedAt) r.Equal(int(t0.Unix()), v.UpdatedAt) From fbf43b40345df1181eff33cc7f623895413d877e Mon Sep 17 00:00:00 2001 From: Benjamin Blattberg Date: Tue, 13 Apr 2021 00:53:50 -0500 Subject: [PATCH 12/59] Allow nullable JSONB and resolve MySQL regression (#639) --- dialect_mysql.go | 5 +++-- slices/map.go | 2 ++ slices/map_test.go | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/dialect_mysql.go b/dialect_mysql.go index 5dda6f5d..af4dd3b2 100644 --- a/dialect_mysql.go +++ b/dialect_mysql.go @@ -157,9 +157,10 @@ func (m *mysql) FizzTranslator() fizz.Translator { func (m *mysql) DumpSchema(w io.Writer) error { deets := m.Details() - cmd := exec.Command("mysqldump", "-d", "-h", deets.Host, "-P", deets.Port, "-u", deets.User, fmt.Sprintf("--password=%s", deets.Password), deets.Database) + // Github CI is currently using mysql:5.7 but the mysqldump version doesn't seem to match + cmd := exec.Command("mysqldump", "--column-statistics=0", "-d", "-h", deets.Host, "-P", deets.Port, "-u", deets.User, fmt.Sprintf("--password=%s", deets.Password), deets.Database) if deets.Port == "socket" { - cmd = exec.Command("mysqldump", "-d", "-S", deets.Host, "-u", deets.User, fmt.Sprintf("--password=%s", deets.Password), deets.Database) + cmd = exec.Command("mysqldump", "--column-statistics=0", "-d", "-S", deets.Host, "-u", deets.User, fmt.Sprintf("--password=%s", deets.Password), deets.Database) } return genericDumpSchema(deets, cmd, w) } diff --git a/slices/map.go b/slices/map.go index c99e8a13..7f04eeee 100644 --- a/slices/map.go +++ b/slices/map.go @@ -19,6 +19,8 @@ func (m Map) Interface() interface{} { func (m *Map) Scan(src interface{}) error { var b []byte switch t := src.(type) { + case nil: + return nil case []byte: b = t case string: diff --git a/slices/map_test.go b/slices/map_test.go index 265d9940..f18dc418 100644 --- a/slices/map_test.go +++ b/slices/map_test.go @@ -35,3 +35,18 @@ func Test_Map_UnMarshalJSON_uninitialized_map_does_not_panic(t *testing.T) { r.Len(maps, 1) }) } + +func Test_Map_Scan(t *testing.T) { + r := require.New(t) + in := []byte(`{"a":"b"}`) + m := Map{} + r.NoError(m.Scan(in)) + r.Equal("b", m["a"]) +} + +func Test_Map_Null_Scan(t *testing.T) { + r := require.New(t) + m := Map{} + r.NoError(m.Scan(nil)) + r.Equal(Map{}, m) +} From 1b7b5ef629eccb4c7a4b5b167363e061ad94d11f Mon Sep 17 00:00:00 2001 From: Jonathan Duck Date: Tue, 13 Apr 2021 09:44:58 -0700 Subject: [PATCH 13/59] Allow passing args to `Order` (#630) --- query.go | 8 ++++---- query_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/query.go b/query.go index b9af3998..ba981ef5 100644 --- a/query.go +++ b/query.go @@ -145,19 +145,19 @@ func (q *Query) Where(stmt string, args ...interface{}) *Query { // Order will append an order clause to the query. // // c.Order("name desc") -func (c *Connection) Order(stmt string) *Query { - return Q(c).Order(stmt) +func (c *Connection) Order(stmt string, args ...interface{}) *Query { + return Q(c).Order(stmt, args...) } // Order will append an order clause to the query. // // q.Order("name desc") -func (q *Query) Order(stmt string) *Query { +func (q *Query) Order(stmt string, args ...interface{}) *Query { if q.RawSQL.Fragment != "" { log(logging.Warn, "Query is setup to use raw SQL") return q } - q.orderClauses = append(q.orderClauses, clause{stmt, []interface{}{}}) + q.orderClauses = append(q.orderClauses, clause{stmt, args}) return q } diff --git a/query_test.go b/query_test.go index 7df5a994..89668361 100644 --- a/query_test.go +++ b/query_test.go @@ -118,6 +118,34 @@ func Test_Order(t *testing.T) { a.Equal(ts("SELECT enemies.A FROM enemies AS enemies ORDER BY id desc, name desc"), sql) } +func Test_Order_With_Args(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + r := require.New(t) + transaction(func(tx *Connection) { + u1 := &Song{Title: "A"} + u2 := &Song{Title: "B"} + u3 := &Song{Title: "C"} + err := tx.Create(u1) + r.NoError(err) + err = tx.Create(u2) + r.NoError(err) + err = tx.Create(u3) + r.NoError(err) + + var songs []Song + err = tx.Where("id in (?)", []uuid.UUID{u1.ID, u2.ID, u3.ID}). + Order("title > ? DESC", "A").Order("title"). + All(&songs) + r.NoError(err) + r.Len(songs, 3) + r.Equal("B", songs[0].Title) + r.Equal("C", songs[1].Title) + r.Equal("A", songs[2].Title) + }) +} + func Test_GroupBy(t *testing.T) { if PDB == nil { t.Skip("skipping integration tests") From 83cf49c8b01e31391dd21c40c391757f76274aa6 Mon Sep 17 00:00:00 2001 From: Arthur Knoepflin Date: Wed, 14 Apr 2021 10:33:27 +0200 Subject: [PATCH 14/59] Added connection maximum idle time configuration (#635) This PR add the possibility to configure the connection maximum idle time (https://golang.org/pkg/database/sql/#DB.SetConnMaxIdleTime). Closes #632 BREAKING CHANGE: Requires Go 1.15 from now on. --- .github/workflows/release.yml | 4 ++-- .github/workflows/tests.yml | 10 +++++----- connection.go | 6 +++++- connection_details.go | 2 ++ go.mod | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 638371b3..08c77532 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: name: Release runs-on: ubuntu-latest container: - image: bepsays/ci-goreleaser:1.13-4 + image: bepsays/ci-goreleaser:1.15.1 steps: - name: Checkout Code uses: actions/checkout@master @@ -24,4 +24,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN }} with: version: latest - args: release --rm-dist \ No newline at end of file + args: release --rm-dist diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4b1b3129..1e5f5583 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.13 + go-version: 1.15 id: go - name: Checkout Code uses: actions/checkout@v1 @@ -64,7 +64,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.13 + go-version: 1.15 id: go - name: Checkout Code uses: actions/checkout@v1 @@ -97,7 +97,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.13 + go-version: 1.15 id: go - name: Checkout Code uses: actions/checkout@v1 @@ -139,7 +139,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.13 + go-version: 1.15 id: go - name: Checkout Code uses: actions/checkout@v1 @@ -181,7 +181,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.13 + go-version: 1.15 id: go - name: Checkout Code uses: actions/checkout@v1 diff --git a/connection.go b/connection.go index 6e0f55ee..91d299bd 100644 --- a/connection.go +++ b/connection.go @@ -5,9 +5,10 @@ import ( "sync/atomic" "time" + "github.com/pkg/errors" + "github.com/gobuffalo/pop/v5/internal/defaults" "github.com/gobuffalo/pop/v5/internal/randx" - "github.com/pkg/errors" ) // Connections contains all available connections @@ -117,6 +118,9 @@ func (c *Connection) Open() error { if details.ConnMaxLifetime > 0 { db.SetConnMaxLifetime(details.ConnMaxLifetime) } + if details.ConnMaxIdleTime > 0 { + db.SetConnMaxIdleTime(details.ConnMaxIdleTime) + } if details.Unsafe { db = db.Unsafe() } diff --git a/connection_details.go b/connection_details.go index 6456b7d1..d7a7ff37 100644 --- a/connection_details.go +++ b/connection_details.go @@ -44,6 +44,8 @@ type ConnectionDetails struct { IdlePool int // Defaults to 0 "unlimited". See https://golang.org/pkg/database/sql/#DB.SetConnMaxLifetime ConnMaxLifetime time.Duration + // Defaults to 0 "unlimited". See https://golang.org/pkg/database/sql/#DB.SetConnMaxIdleTime + ConnMaxIdleTime time.Duration // Defaults to `false`. See https://godoc.org/github.com/jmoiron/sqlx#DB.Unsafe Unsafe bool Options map[string]string diff --git a/go.mod b/go.mod index 346ac0ee..24f40eef 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/gobuffalo/pop/v5 -go 1.13 +go 1.15 replace github.com/mattn/go-sqlite3 => github.com/mattn/go-sqlite3 v1.14.0 From 51f7117690483b5268a50d77417d43687e2eefd9 Mon Sep 17 00:00:00 2001 From: hackerman <3372410+aeneasr@users.noreply.github.com> Date: Tue, 27 Apr 2021 14:47:47 +0200 Subject: [PATCH 15/59] Bump sqlite to 3.35.4 / 1.14.7 (#642) --- go.mod | 2 +- go.sum | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 24f40eef..59de20a9 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/gobuffalo/pop/v5 go 1.15 -replace github.com/mattn/go-sqlite3 => github.com/mattn/go-sqlite3 v1.14.0 +replace github.com/mattn/go-sqlite3 => github.com/mattn/go-sqlite3 v1.14.7 require ( github.com/fatih/color v1.9.0 diff --git a/go.sum b/go.sum index e00ce20b..41130dae 100644 --- a/go.sum +++ b/go.sum @@ -3,10 +3,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/Masterminds/semver/v3 v3.0.3 h1:znjIyLfpXEDQjOIEWh+ehwpTU14UzUPub3c3sm36u14= github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -195,8 +193,8 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= -github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= +github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= @@ -295,7 +293,6 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -306,9 +303,8 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -329,9 +325,8 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= From cf0a600b9d9d25ceec6be13148f7ada22cf09ed1 Mon Sep 17 00:00:00 2001 From: Antonio Pagano <645522+paganotoni@users.noreply.github.com> Date: Wed, 5 May 2021 01:21:50 -0500 Subject: [PATCH 16/59] Update pg, pgx, sqlx (#643) - `jackc/pgx` to version `v4.11.0`. - `jmoiron/sqlx` to version`v1.3.3` - `lib/pq` to version`v1.10.1` --- go.mod | 8 +- go.sum | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 59de20a9..2438e454 100644 --- a/go.mod +++ b/go.mod @@ -20,11 +20,11 @@ require ( github.com/gobuffalo/plush/v4 v4.0.0 github.com/gobuffalo/validate/v3 v3.1.0 github.com/gofrs/uuid v3.2.0+incompatible - github.com/jackc/pgconn v1.8.0 - github.com/jackc/pgx/v4 v4.10.1 - github.com/jmoiron/sqlx v1.2.0 + github.com/jackc/pgconn v1.8.1 + github.com/jackc/pgx/v4 v4.11.0 + github.com/jmoiron/sqlx v1.3.3 github.com/karrick/godirwalk v1.16.1 // indirect - github.com/lib/pq v1.3.0 + github.com/lib/pq v1.10.1 github.com/luna-duclos/instrumentedsql v1.1.3 github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 41130dae..7b90664d 100644 --- a/go.sum +++ b/go.sum @@ -1,23 +1,53 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/semver/v3 v3.0.3 h1:znjIyLfpXEDQjOIEWh+ehwpTU14UzUPub3c3sm36u14= github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -25,15 +55,29 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -74,23 +118,64 @@ github.com/gobuffalo/validate/v3 v3.1.0 h1:/QQN920PciCfBs3aywtJTvDTHmBFMKoiwkshU github.com/gobuffalo/validate/v3 v3.1.0/go.mod h1:HFpjq+AIiA2RHoQnQVTFKF/ZpUPXwyw82LgyDPxQ9r0= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -104,6 +189,8 @@ github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.8.0 h1:FmjZ0rOyXTr1wfWs45i4a9vjnjWUAGpMuQLD9OSs+lw= github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.8.1 h1:ySBX7Q87vOMqKU2bbmKbUvtYhauDFclYbNDYIE1/h6s= +github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA= @@ -130,6 +217,8 @@ github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkAL github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= github.com/jackc/pgtype v1.6.2 h1:b3pDeuhbbzBYcg5kwNmNDun4pFUD/0AAr1kLXZLeNt8= github.com/jackc/pgtype v1.6.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= +github.com/jackc/pgtype v1.7.0 h1:6f4kVsW01QftE38ufBYxKciO6gyioXSC0ABIRLcZrGs= +github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= @@ -138,16 +227,25 @@ github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6 github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= github.com/jackc/pgx/v4 v4.10.1 h1:/6Q3ye4myIj6AaplUm+eRcz4OhK9HAvFf4ePsG40LJY= github.com/jackc/pgx/v4 v4.10.1/go.mod h1:QlrWebbs3kqEZPHCTGyxecvzG6tvIsYu+A5b1raylkA= +github.com/jackc/pgx/v4 v4.11.0 h1:J86tSWd3Y7nKjwT/43xZBvpi04keQWx8gNC2YkdJhZI= +github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jmoiron/sqlx v1.3.3 h1:j82X0bf7oQ27XeqxicSZsTU5suPwKElg3oyxNn43iTk= +github.com/jmoiron/sqlx v1.3.3/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karrick/godirwalk v1.15.3/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= @@ -172,8 +270,13 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.1 h1:6VXZrLU0jHBYyAqrSPa+MgPfnSvTPuMgK+k0o5kVFWo= +github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/luna-duclos/instrumentedsql v1.1.3 h1:t7mvC0z1jUt5A0UQ6I/0H31ryymuQRnJcWCiqV3lSAA= github.com/luna-duclos/instrumentedsql v1.1.3/go.mod h1:9J1njvFds+zN7y85EDhN9XNQLANWwZt2ULeIC8yMNYs= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= @@ -181,11 +284,14 @@ github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -193,31 +299,86 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -227,7 +388,10 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -239,7 +403,10 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= @@ -247,12 +414,17 @@ github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -261,24 +433,37 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -286,62 +471,95 @@ golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200308013534-11ec41452d41 h1:9Di9iYgOt9ThCipBxChBVhgNipDoE5mxO84rQV7D0FE= golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= @@ -351,23 +569,46 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From 96f8e48ad80824f5d44821fd4b5c93f2cc854f40 Mon Sep 17 00:00:00 2001 From: Larry Morales Jordan Date: Wed, 5 May 2021 14:56:36 -0500 Subject: [PATCH 17/59] Fix Inner has many associations when passing on multiple arguments (#633) * Fix Inner has many associations when passing on multiple arguments for inner fields * Fix broken tests * clean up extractFieldAndInnerFields function Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> --- associations/association.go | 2 +- associations/associations_for_struct.go | 39 +++++++++++++----- finders.go | 6 ++- finders_test.go | 40 +++++++++++++++++++ pop_test.go | 4 ++ .../20181104135526_good_friends.up.fizz | 1 + .../20181104140340_addresses.up.fizz | 1 + 7 files changed, 81 insertions(+), 12 deletions(-) diff --git a/associations/association.go b/associations/association.go index 0bda8694..8fa335fd 100644 --- a/associations/association.go +++ b/associations/association.go @@ -43,7 +43,7 @@ func (a *associationComposite) InnerAssociations() InnerAssociations { // association for Song. type InnerAssociation struct { Name string - Fields string + Fields []string } // InnerAssociations is a group of InnerAssociation. diff --git a/associations/associations_for_struct.go b/associations/associations_for_struct.go index b7c4742f..368e72c0 100644 --- a/associations/associations_for_struct.go +++ b/associations/associations_for_struct.go @@ -34,29 +34,39 @@ func ForStruct(s interface{}, fields ...string) (Associations, error) { } fields = trimFields(fields) associations := Associations{} - innerAssociations := InnerAssociations{} + fieldsWithInnerAssociation := map[string]InnerAssociations{} // validate if fields contains a non existing field in struct. // and verify is it has inner associations. for i := range fields { - var innerField, field string + var innerField string if !validAssociationExpRegexp.MatchString(fields[i]) { return associations, fmt.Errorf("association '%s' does not match the format %s", fields[i], "'' or '.'") } - if strings.Contains(fields[i], ".") { - dotIndex := strings.Index(fields[i], ".") - field = fields[i][:dotIndex] - innerField = fields[i][dotIndex+1:] - fields[i] = field - } + fields[i], innerField = extractFieldAndInnerFields(fields[i]) + if _, ok := t.FieldByName(fields[i]); !ok { return associations, fmt.Errorf("field %s does not exist in model %s", fields[i], t.Name()) } if innerField != "" { - innerAssociations = append(innerAssociations, InnerAssociation{fields[i], innerField}) + var found bool + innerF, _ := extractFieldAndInnerFields(innerField) + + for j := range fieldsWithInnerAssociation[fields[i]] { + f, _ := extractFieldAndInnerFields(fieldsWithInnerAssociation[fields[i]][j].Fields[0]) + if innerF == f { + fieldsWithInnerAssociation[fields[i]][j].Fields = append(fieldsWithInnerAssociation[fields[i]][j].Fields, innerField) + found = true + break + } + } + + if !found { + fieldsWithInnerAssociation[fields[i]] = append(fieldsWithInnerAssociation[fields[i]], InnerAssociation{fields[i], []string{innerField}}) + } } } @@ -79,7 +89,7 @@ func ForStruct(s interface{}, fields ...string) (Associations, error) { modelType: t, modelValue: v, popTags: tags, - innerAssociations: innerAssociations, + innerAssociations: fieldsWithInnerAssociation[f.Name], } a, err := builder(params) @@ -121,3 +131,12 @@ func fieldIgnoredIn(fields []string, field string) bool { } return true } + +func extractFieldAndInnerFields(field string) (string, string) { + if !strings.Contains(field, ".") { + return field, "" + } + + dotIndex := strings.Index(field, ".") + return field[:dotIndex], field[dotIndex+1:] +} diff --git a/finders.go b/finders.go index fa1a220a..7de66924 100644 --- a/finders.go +++ b/finders.go @@ -273,12 +273,16 @@ func (q *Query) eagerDefaultAssociations(model interface{}) error { return err } + if err == sql.ErrNoRows { + continue + } + // load all inner associations. innerAssociations := association.InnerAssociations() for _, inner := range innerAssociations { v = reflect.Indirect(reflect.ValueOf(model)).FieldByName(inner.Name) innerQuery := Q(query.Connection) - innerQuery.eagerFields = []string{inner.Fields} + innerQuery.eagerFields = inner.Fields err = innerQuery.eagerAssociations(v.Addr().Interface()) if err != nil { return err diff --git a/finders_test.go b/finders_test.go index 7f30727e..7e2daa02 100644 --- a/finders_test.go +++ b/finders_test.go @@ -908,3 +908,43 @@ func Test_FindManyToMany(t *testing.T) { r.NoError(err) }) } + +func Test_FindMultipleInnerHasMany(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + user := User{Name: nulls.NewString("Mark")} + err := tx.Create(&user) + r.NoError(err) + + book := Book{Title: "Pop Book", Isbn: "PB1", UserID: nulls.NewInt(user.ID)} + err = tx.Create(&book) + r.NoError(err) + + writer := Writer{Name: "Jhon", BookID: book.ID} + err = tx.Create(&writer) + r.NoError(err) + + friend := Friend{FirstName: "Frank", LastName: "Kafka", WriterID: writer.ID} + err = tx.Create(&friend) + r.NoError(err) + + address := Address{Street: "St 27", HouseNumber: 27, WriterID: writer.ID} + err = tx.Create(&address) + r.NoError(err) + + u := User{} + err = tx.Eager("Books.Writers.Addresses", "Books.Writers.Friends").Find(&u, user.ID) + r.NoError(err) + + r.Len(u.Books, 1) + r.Len(u.Books[0].Writers, 1) + r.Len(u.Books[0].Writers[0].Addresses, 1) + r.Equal(u.Books[0].Writers[0].Addresses[0].HouseNumber, 27) + r.Len(u.Books[0].Writers[0].Friends, 1) + r.Equal(u.Books[0].Writers[0].Friends[0].FirstName, "Frank") + }) +} diff --git a/pop_test.go b/pop_test.go index 1d473de0..1e02497e 100644 --- a/pop_test.go +++ b/pop_test.go @@ -163,6 +163,8 @@ type Books []Book type Writer struct { ID int `db:"id"` Name string `db:"name"` + Addresses Addresses `has_many:"addresses"` + Friends []Friend `has_many:"friends"` BookID int `db:"book_id"` Book Book `belongs_to:"book"` CreatedAt time.Time `db:"created_at"` @@ -174,6 +176,7 @@ type Writers []Writer type Address struct { ID int `db:"id"` Street string `db:"street"` + WriterID int `db:"writer_id"` HouseNumber int `db:"house_number"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` @@ -207,6 +210,7 @@ func (UsersAddressQuery) TableName() string { type Friend struct { ID int `db:"id"` FirstName string `db:"first_name"` + WriterID int `db:"writer_id"` LastName string `db:"last_name"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` diff --git a/testdata/migrations/20181104135526_good_friends.up.fizz b/testdata/migrations/20181104135526_good_friends.up.fizz index 61e24d3c..211c3848 100644 --- a/testdata/migrations/20181104135526_good_friends.up.fizz +++ b/testdata/migrations/20181104135526_good_friends.up.fizz @@ -2,5 +2,6 @@ create_table("good_friends") { t.Column("id", "int", {primary: true}) t.Column("first_name", "string", {}) t.Column("last_name", "string", {}) + t.Column("writer_id", "int",{}) t.Timestamps() } \ No newline at end of file diff --git a/testdata/migrations/20181104140340_addresses.up.fizz b/testdata/migrations/20181104140340_addresses.up.fizz index d57d70af..6520f03b 100644 --- a/testdata/migrations/20181104140340_addresses.up.fizz +++ b/testdata/migrations/20181104140340_addresses.up.fizz @@ -2,5 +2,6 @@ create_table("addresses") { t.Column("id", "int", {primary: true}) t.Column("street", "string", {}) t.Column("house_number", "int", {}) + t.Column("writer_id", "int",{}) t.Timestamps() } \ No newline at end of file From aeb9b56f19f069f8639aec993aee4bfa6432d995 Mon Sep 17 00:00:00 2001 From: Larry Morales Jordan Date: Thu, 6 May 2021 08:07:23 -0500 Subject: [PATCH 18/59] Remove many to many TX condition for EagerPreload (#645) * Remove the need to use Tx when loading many to many associations * replace TX access to create a new tx.Store.Transaction() object --- preload_associations.go | 105 +++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/preload_associations.go b/preload_associations.go index c7c8b6c5..1ba4d5a2 100644 --- a/preload_associations.go +++ b/preload_associations.go @@ -437,72 +437,77 @@ func preloadManyToMany(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMeta manyToManyTableName = strings.TrimSpace(manyToManyTableName[:strings.Index(manyToManyTableName, ":")]) } - if tx.TX != nil { - sql := fmt.Sprintf("SELECT %s, %s FROM %s WHERE %s in (?)", modelAssociationName, assocFkName, manyToManyTableName, modelAssociationName) - sql, args, _ := sqlx.In(sql, ids) - sql = tx.Dialect.TranslateSQL(sql) - log(logging.SQL, sql, args...) - rows, err := tx.TX.Queryx(sql, args...) + sql := fmt.Sprintf("SELECT %s, %s FROM %s WHERE %s in (?)", modelAssociationName, assocFkName, manyToManyTableName, modelAssociationName) + sql, args, _ := sqlx.In(sql, ids) + sql = tx.Dialect.TranslateSQL(sql) + log(logging.SQL, sql, args...) + + cn, err := tx.Store.Transaction() + if err != nil { + return err + } + + rows, err := cn.Queryx(sql, args...) + if err != nil { + return err + } + + mapAssoc := map[string][]interface{}{} + fkids := []interface{}{} + for rows.Next() { + row, err := rows.SliceScan() if err != nil { return err } - - mapAssoc := map[string][]interface{}{} - fkids := []interface{}{} - for rows.Next() { - row, err := rows.SliceScan() - if err != nil { - return err + if len(row) > 0 { + if _, ok := row[0].([]uint8); ok { // -> it's UUID + row[0] = string(row[0].([]uint8)) } - if len(row) > 0 { - if _, ok := row[0].([]uint8); ok { // -> it's UUID - row[0] = string(row[0].([]uint8)) - } - if _, ok := row[1].([]uint8); ok { // -> it's UUID - row[1] = string(row[1].([]uint8)) - } - key := fmt.Sprintf("%v", row[0]) - mapAssoc[key] = append(mapAssoc[key], row[1]) - fkids = append(fkids, row[1]) + if _, ok := row[1].([]uint8); ok { // -> it's UUID + row[1] = string(row[1].([]uint8)) } + key := fmt.Sprintf("%v", row[0]) + mapAssoc[key] = append(mapAssoc[key], row[1]) + fkids = append(fkids, row[1]) } + } - q := tx.Q() - q.eager = false - q.eagerFields = []string{} + q := tx.Q() + q.eager = false + q.eagerFields = []string{} - if strings.TrimSpace(asoc.Field.Tag.Get("order_by")) != "" { - q.Order(asoc.Field.Tag.Get("order_by")) - } + if strings.TrimSpace(asoc.Field.Tag.Get("order_by")) != "" { + q.Order(asoc.Field.Tag.Get("order_by")) + } - slice := asoc.toSlice() - q.Where("id in (?)", fkids).All(slice.Interface()) + slice := asoc.toSlice() + q.Where("id in (?)", fkids).All(slice.Interface()) - // 2.2) load all nested associations from this assoc. - if asocNestedFields, ok := mmi.nestedFields[asoc.Path]; ok { - for _, asocNestedField := range asocNestedFields { - if err := preload(tx, slice.Interface(), asocNestedField); err != nil { - return err - } + // 2.2) load all nested associations from this assoc. + if asocNestedFields, ok := mmi.nestedFields[asoc.Path]; ok { + for _, asocNestedField := range asocNestedFields { + if err := preload(tx, slice.Interface(), asocNestedField); err != nil { + return err } } + } - // 3) iterate over every model and fill it with the assoc. - mmi.iterate(func(mvalue reflect.Value) { - id := mmi.mapper.FieldByName(mvalue, "ID").Interface() - if assocFkIds, ok := mapAssoc[fmt.Sprintf("%v", id)]; ok { - modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) - for i := 0; i < slice.Elem().Len(); i++ { - asocValue := slice.Elem().Index(i) - for _, fkid := range assocFkIds { - if fmt.Sprintf("%v", fkid) == fmt.Sprintf("%v", mmi.mapper.FieldByName(asocValue, "ID").Interface()) { - modelAssociationField.Set(reflect.Append(modelAssociationField, asocValue)) - } + // 3) iterate over every model and fill it with the assoc. + mmi.iterate(func(mvalue reflect.Value) { + id := mmi.mapper.FieldByName(mvalue, "ID").Interface() + if assocFkIds, ok := mapAssoc[fmt.Sprintf("%v", id)]; ok { + modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) + for i := 0; i < slice.Elem().Len(); i++ { + asocValue := slice.Elem().Index(i) + for _, fkid := range assocFkIds { + if fmt.Sprintf("%v", fkid) == fmt.Sprintf("%v", mmi.mapper.FieldByName(asocValue, "ID").Interface()) { + modelAssociationField.Set(reflect.Append(modelAssociationField, asocValue)) } } } - }) - } + } + }) + return nil } From bef765a5919489a05dfa4de5a81709ff41e767b2 Mon Sep 17 00:00:00 2001 From: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Date: Thu, 6 May 2021 09:24:55 -0400 Subject: [PATCH 19/59] Added fix/tests for has_many with pointer foreign key (#647) Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> --- pop_test.go | 3 +++ preload_associations.go | 5 +++-- preload_associations_test.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pop_test.go b/pop_test.go index 1e02497e..107ec86d 100644 --- a/pop_test.go +++ b/pop_test.go @@ -150,6 +150,8 @@ type Taxi struct { UpdatedAt time.Time `db:"updated_at"` } +type Taxis []Taxi + // Validate gets run every time you call a "Validate*" (ValidateAndSave, ValidateAndCreate, ValidateAndUpdate) method. // This method is not required and may be deleted. func (b *Book) Validate(tx *Connection) (*validate.Errors, error) { @@ -180,6 +182,7 @@ type Address struct { HouseNumber int `db:"house_number"` CreatedAt time.Time `db:"created_at"` UpdatedAt time.Time `db:"updated_at"` + TaxisToHere Taxis `has_many:"taxis" fk_id:"to_address_id" order_by:"created_at asc"` } type Addresses []Address diff --git a/preload_associations.go b/preload_associations.go index 1ba4d5a2..1498cf8b 100644 --- a/preload_associations.go +++ b/preload_associations.go @@ -271,8 +271,9 @@ func preloadHasMany(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMetaInf modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) for i := 0; i < slice.Elem().Len(); i++ { asocValue := slice.Elem().Index(i) - if mmi.mapper.FieldByName(mvalue, "ID").Interface() == mmi.mapper.FieldByName(asocValue, foreignField.Path).Interface() || - reflect.DeepEqual(mmi.mapper.FieldByName(mvalue, "ID"), mmi.mapper.FieldByName(asocValue, foreignField.Path)) { + valueField := reflect.Indirect(mmi.mapper.FieldByName(asocValue, foreignField.Path)) + if mmi.mapper.FieldByName(mvalue, "ID").Interface() == valueField.Interface() || + reflect.DeepEqual(mmi.mapper.FieldByName(mvalue, "ID"), valueField) { switch { case modelAssociationField.Kind() == reflect.Slice || modelAssociationField.Kind() == reflect.Array: diff --git a/preload_associations_test.go b/preload_associations_test.go index 9d735fd4..879531c2 100644 --- a/preload_associations_test.go +++ b/preload_associations_test.go @@ -264,3 +264,39 @@ func Test_New_Implementation_For_BelongsTo_Ptr_Field(t *testing.T) { SetEagerMode(EagerDefault) }) } + +func Test_New_Implementation_For_HasMany_Ptr_Field(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + a := require.New(t) + toAddress1 := Address{HouseNumber: 1, Street: "Destination Ave"} + a.NoError(tx.Create(&toAddress1)) + taxi1 := Taxi{Model: "Ford", ToAddressID: &toAddress1.ID} + a.NoError(tx.Create(&taxi1)) + taxi2 := Taxi{Model: "Honda", ToAddressID: &toAddress1.ID} + a.NoError(tx.Create(&taxi2)) + + taxiNilToAddress := Taxi{ToAddressID: nil} + a.NoError(tx.Create(&taxiNilToAddress)) + + toAddress2 := Address{HouseNumber: 2, Street: "Final Way"} + a.NoError(tx.Create(&toAddress2)) + taxi3 := Taxi{Model: "Mazda", ToAddressID: &toAddress2.ID} + a.NoError(tx.Create(&taxi3)) + + SetEagerMode(EagerPreload) + addresses := []Address{} + a.NoError(tx.EagerPreload("TaxisToHere").Order("created_at").All(&addresses)) + a.Len(addresses, 2) + a.NotNil(addresses[0].TaxisToHere) + a.Len(addresses[0].TaxisToHere, 2) + a.Equal(taxi1.Model, addresses[0].TaxisToHere[0].Model) + a.Equal(taxi2.Model, addresses[0].TaxisToHere[1].Model) + a.NotNil(addresses[1].TaxisToHere) + a.Len(addresses[1].TaxisToHere, 1) + a.Equal(taxi3.Model, addresses[1].TaxisToHere[0].Model) + SetEagerMode(EagerDefault) + }) +} From bb07a373cc0e689f778a9701c84d61a1c58f314c Mon Sep 17 00:00:00 2001 From: hackerman <3372410+aeneasr@users.noreply.github.com> Date: Tue, 8 Jun 2021 12:57:45 +0200 Subject: [PATCH 20/59] Export WhereID, Alias, WhereNamedID (#637) This patch export some model convenience functions which are useful when constructing queries outside of pop: custom updates, deletes, inserts, ... Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> --- dialect_cockroach.go | 2 +- dialect_common.go | 4 ++-- dialect_postgresql.go | 2 +- finders.go | 2 +- model.go | 10 +++++----- model_test.go | 4 ++-- sql_builder.go | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/dialect_cockroach.go b/dialect_cockroach.go index cab020a5..d8dd0a08 100644 --- a/dialect_cockroach.go +++ b/dialect_cockroach.go @@ -105,7 +105,7 @@ func (p *cockroach) Update(s store, model *Model, cols columns.Columns) error { } func (p *cockroach) Destroy(s store, model *Model) error { - stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", p.Quote(model.TableName()), model.alias(), model.whereID())) + stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", p.Quote(model.TableName()), model.Alias(), model.WhereID())) _, err := genericExec(s, stmt, model.ID()) return err } diff --git a/dialect_common.go b/dialect_common.go index 7da27adb..0905b049 100644 --- a/dialect_common.go +++ b/dialect_common.go @@ -99,7 +99,7 @@ func genericCreate(s store, model *Model, cols columns.Columns, quoter quotable) } func genericUpdate(s store, model *Model, cols columns.Columns, quoter quotable) error { - stmt := fmt.Sprintf("UPDATE %s AS %s SET %s WHERE %s", quoter.Quote(model.TableName()), model.alias(), cols.Writeable().QuotedUpdateString(quoter), model.whereNamedID()) + stmt := fmt.Sprintf("UPDATE %s AS %s SET %s WHERE %s", quoter.Quote(model.TableName()), model.Alias(), cols.Writeable().QuotedUpdateString(quoter), model.WhereNamedID()) log(logging.SQL, stmt, model.ID()) _, err := s.NamedExec(stmt, model.Value) if err != nil { @@ -109,7 +109,7 @@ func genericUpdate(s store, model *Model, cols columns.Columns, quoter quotable) } func genericDestroy(s store, model *Model, quoter quotable) error { - stmt := fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", quoter.Quote(model.TableName()), model.alias(), model.whereID()) + stmt := fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", quoter.Quote(model.TableName()), model.Alias(), model.WhereID()) _, err := genericExec(s, stmt, model.ID()) if err != nil { return err diff --git a/dialect_postgresql.go b/dialect_postgresql.go index ccb8e43d..3590141e 100644 --- a/dialect_postgresql.go +++ b/dialect_postgresql.go @@ -92,7 +92,7 @@ func (p *postgresql) Update(s store, model *Model, cols columns.Columns) error { } func (p *postgresql) Destroy(s store, model *Model) error { - stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", p.Quote(model.TableName()), model.alias(), model.whereID())) + stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", p.Quote(model.TableName()), model.Alias(), model.WhereID())) _, err := genericExec(s, stmt, model.ID()) if err != nil { return err diff --git a/finders.go b/finders.go index 7de66924..440fb703 100644 --- a/finders.go +++ b/finders.go @@ -30,7 +30,7 @@ func (c *Connection) Find(model interface{}, id interface{}) error { // q.Find(&User{}, 1) func (q *Query) Find(model interface{}, id interface{}) error { m := NewModel(model, q.Connection.Context()) - idq := m.whereID() + idq := m.WhereID() switch t := id.(type) { case uuid.UUID: return q.Where(idq, t.String()).First(model) diff --git a/model.go b/model.go index a8625551..d83ee380 100644 --- a/model.go +++ b/model.go @@ -219,11 +219,11 @@ func (m *Model) setUpdatedAt(now time.Time) { } } -func (m *Model) whereID() string { - return fmt.Sprintf("%s.%s = ?", m.alias(), m.IDField()) +func (m *Model) WhereID() string { + return fmt.Sprintf("%s.%s = ?", m.Alias(), m.IDField()) } -func (m *Model) alias() string { +func (m *Model) Alias() string { as := m.As if as == "" { as = strings.ReplaceAll(m.TableName(), ".", "_") @@ -231,8 +231,8 @@ func (m *Model) alias() string { return as } -func (m *Model) whereNamedID() string { - return fmt.Sprintf("%s.%s = :%s", m.alias(), m.IDField(), m.IDField()) +func (m *Model) WhereNamedID() string { + return fmt.Sprintf("%s.%s = :%s", m.Alias(), m.IDField(), m.IDField()) } func (m *Model) isSlice() bool { diff --git a/model_test.go b/model_test.go index 6f9a6f79..1bcc7e2d 100644 --- a/model_test.go +++ b/model_test.go @@ -207,8 +207,8 @@ func Test_WhereID(t *testing.T) { r := require.New(t) m := Model{Value: &testPrefixID{ID: 1}} - r.Equal("foo_bar.custom_id = ?", m.whereID()) - r.Equal("foo_bar.custom_id = :custom_id", m.whereNamedID()) + r.Equal("foo_bar.custom_id = ?", m.WhereID()) + r.Equal("foo_bar.custom_id = :custom_id", m.WhereNamedID()) type testNormalID struct { ID int diff --git a/sql_builder.go b/sql_builder.go index 44820f4e..b6e07223 100644 --- a/sql_builder.go +++ b/sql_builder.go @@ -125,7 +125,7 @@ func (sq *sqlBuilder) buildfromClauses() fromClauses { fc := sq.Query.fromClauses for _, m := range models { tableName := m.TableName() - asName := m.alias() + asName := m.Alias() fc = append(fc, fromClause{ From: tableName, As: asName, @@ -213,7 +213,7 @@ var columnCacheMutex = sync.RWMutex{} func (sq *sqlBuilder) buildColumns() columns.Columns { tableName := sq.Model.TableName() - asName := sq.Model.alias() + asName := sq.Model.Alias() acl := len(sq.AddColumns) if acl == 0 { columnCacheMutex.RLock() From d2790005a2ff33b3e9e128ce09a9591ba5e44e75 Mon Sep 17 00:00:00 2001 From: Patrik Date: Mon, 28 Jun 2021 15:40:45 +0200 Subject: [PATCH 21/59] fix: log model values everywhere (#656) Some SQL logs were missing the values as argument. This adds all places --- dialect_cockroach.go | 2 +- dialect_common.go | 4 ++-- dialect_postgresql.go | 2 +- dialect_sqlite.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dialect_cockroach.go b/dialect_cockroach.go index d8dd0a08..9e933336 100644 --- a/dialect_cockroach.go +++ b/dialect_cockroach.go @@ -81,7 +81,7 @@ func (p *cockroach) Create(s store, model *Model, cols columns.Columns) error { } else { query = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES returning %s", p.Quote(model.TableName()), model.IDField()) } - log(logging.SQL, query) + log(logging.SQL, query, model.Value) stmt, err := s.PrepareNamed(query) if err != nil { return err diff --git a/dialect_common.go b/dialect_common.go index 0905b049..79d0d190 100644 --- a/dialect_common.go +++ b/dialect_common.go @@ -53,7 +53,7 @@ func genericCreate(s store, model *Model, cols columns.Columns, quoter quotable) cols.Remove(model.IDField()) w := cols.Writeable() query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", quoter.Quote(model.TableName()), w.QuotedString(quoter), w.SymbolizedString()) - log(logging.SQL, query) + log(logging.SQL, query, model.Value) res, err := s.NamedExec(query, model.Value) if err != nil { return err @@ -81,7 +81,7 @@ func genericCreate(s store, model *Model, cols columns.Columns, quoter quotable) w := cols.Writeable() w.Add(model.IDField()) query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", quoter.Quote(model.TableName()), w.QuotedString(quoter), w.SymbolizedString()) - log(logging.SQL, query) + log(logging.SQL, query, model.Value) stmt, err := s.PrepareNamed(query) if err != nil { return err diff --git a/dialect_postgresql.go b/dialect_postgresql.go index 3590141e..ad5b2350 100644 --- a/dialect_postgresql.go +++ b/dialect_postgresql.go @@ -68,7 +68,7 @@ func (p *postgresql) Create(s store, model *Model, cols columns.Columns) error { } else { query = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES returning %s", p.Quote(model.TableName()), model.IDField()) } - log(logging.SQL, query) + log(logging.SQL, query, model.Value) stmt, err := s.PrepareNamed(query) if err != nil { return err diff --git a/dialect_sqlite.go b/dialect_sqlite.go index 47bc3e28..c340afa8 100644 --- a/dialect_sqlite.go +++ b/dialect_sqlite.go @@ -82,7 +82,7 @@ func (m *sqlite) Create(s store, model *Model, cols columns.Columns) error { } else { query = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES", m.Quote(model.TableName())) } - log(logging.SQL, query) + log(logging.SQL, query, model.Value) res, err := s.NamedExec(query, model.Value) if err != nil { return err From 0ecad2589ac4e4c1b830d837f00de357c7165920 Mon Sep 17 00:00:00 2001 From: Patrik Date: Fri, 16 Jul 2021 10:01:18 +0200 Subject: [PATCH 22/59] Add delete to query builder (#658) This allows writing delete queries without knowing the exact primary key or for composite keys. `Destroy` only allows to delete by primary key, but there are many cases where you want to delete multiple rows or by some other query than the ID. See #29 --- dialect.go | 1 + dialect_cockroach.go | 4 ++++ dialect_common.go | 6 ++++++ dialect_mysql.go | 10 ++++++++++ dialect_postgresql.go | 4 ++++ dialect_sqlite.go | 4 ++++ docker-compose.yml | 1 + executors.go | 13 +++++++++++++ executors_test.go | 37 ++++++++++++++++++++++++++++++++++++- query.go | 10 ++++++++++ sql_builder.go | 30 +++++++++++++++++++++++++++++- test.sh | 5 +++++ 12 files changed, 123 insertions(+), 2 deletions(-) diff --git a/dialect.go b/dialect.go index dbb4800e..4ff29a3b 100644 --- a/dialect.go +++ b/dialect.go @@ -13,6 +13,7 @@ type crudable interface { Create(store, *Model, columns.Columns) error Update(store, *Model, columns.Columns) error Destroy(store, *Model) error + Delete(store, *Model, Query) error } type fizzable interface { diff --git a/dialect_cockroach.go b/dialect_cockroach.go index 9e933336..5d200d65 100644 --- a/dialect_cockroach.go +++ b/dialect_cockroach.go @@ -110,6 +110,10 @@ func (p *cockroach) Destroy(s store, model *Model) error { return err } +func (p *cockroach) Delete(s store, model *Model, query Query) error { + return genericDelete(s, model, query) +} + func (p *cockroach) SelectOne(s store, model *Model, query Query) error { return genericSelectOne(s, model, query) } diff --git a/dialect_common.go b/dialect_common.go index 79d0d190..5a9eee9c 100644 --- a/dialect_common.go +++ b/dialect_common.go @@ -117,6 +117,12 @@ func genericDestroy(s store, model *Model, quoter quotable) error { return nil } +func genericDelete(s store, model *Model, query Query) error { + sqlQuery, args := query.ToSQL(model) + _, err := genericExec(s, sqlQuery, args...) + return err +} + func genericExec(s store, stmt string, args ...interface{}) (sql.Result, error) { log(logging.SQL, stmt, args...) res, err := s.Exec(stmt, args...) diff --git a/dialect_mysql.go b/dialect_mysql.go index af4dd3b2..dbd9b49b 100644 --- a/dialect_mysql.go +++ b/dialect_mysql.go @@ -96,6 +96,16 @@ func (m *mysql) Destroy(s store, model *Model) error { return errors.Wrap(err, "mysql destroy") } +func (m *mysql) Delete(s store, model *Model, query Query) error { + sb := query.toSQLBuilder(model) + + sql := fmt.Sprintf("DELETE FROM %s", m.Quote(model.TableName())) + sql = sb.buildWhereClauses(sql) + + _, err := genericExec(s, sql, sb.Args()...) + return errors.Wrap(err, "mysql delete") +} + func (m *mysql) SelectOne(s store, model *Model, query Query) error { return errors.Wrap(genericSelectOne(s, model, query), "mysql select one") } diff --git a/dialect_postgresql.go b/dialect_postgresql.go index ad5b2350..6365232e 100644 --- a/dialect_postgresql.go +++ b/dialect_postgresql.go @@ -100,6 +100,10 @@ func (p *postgresql) Destroy(s store, model *Model) error { return nil } +func (p *postgresql) Delete(s store, model *Model, query Query) error { + return genericDelete(s, model, query) +} + func (p *postgresql) SelectOne(s store, model *Model, query Query) error { return genericSelectOne(s, model, query) } diff --git a/dialect_sqlite.go b/dialect_sqlite.go index c340afa8..ce755566 100644 --- a/dialect_sqlite.go +++ b/dialect_sqlite.go @@ -112,6 +112,10 @@ func (m *sqlite) Destroy(s store, model *Model) error { }) } +func (m *sqlite) Delete(s store, model *Model, query Query) error { + return genericDelete(s, model, query) +} + func (m *sqlite) SelectOne(s store, model *Model, query Query) error { return m.locker(m.smGil, func() error { return errors.Wrap(genericSelectOne(s, model, query), "sqlite select one") diff --git a/docker-compose.yml b/docker-compose.yml index 6c058cc8..54b90986 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,6 +25,7 @@ services: - ./sqldumps:/docker-entrypoint-initdb.d cockroach: image: cockroachdb/cockroach:v20.2.4 + user: ${CURRENT_UID:?"Please run as follows 'CURRENT_UID=$(id -u):$(id -g) docker-compose up'"} ports: - "26257:26257" volumes: diff --git a/executors.go b/executors.go index c382f260..eaae29eb 100644 --- a/executors.go +++ b/executors.go @@ -439,3 +439,16 @@ func (c *Connection) Destroy(model interface{}) error { }) }) } + +func (q *Query) Delete(model interface{}) error { + q.Operation = Delete + + return q.Connection.timeFunc("Delete", func() error { + m := NewModel(model, q.Connection.Context()) + err := q.Connection.Dialect.Delete(q.Connection.Store, m, *q) + if err != nil { + return err + } + return m.afterDestroy(q.Connection) + }) +} diff --git a/executors_test.go b/executors_test.go index bee9a5e8..6ec3386e 100644 --- a/executors_test.go +++ b/executors_test.go @@ -313,7 +313,7 @@ func Test_Exec(t *testing.T) { r := require.New(t) user := User{Name: nulls.NewString("Mark 'Awesome' Bates")} - tx.Create(&user) + r.NoError(tx.Create(&user)) ctx, _ := tx.Count(user) r.Equal(1, ctx) @@ -1649,3 +1649,38 @@ func Test_TruncateAll(t *testing.T) { r.Equal(count, ctx) }) } + +func Test_Delete(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + + transaction(func(tx *Connection) { + r := require.New(t) + + songTitles := []string{"Yoshimi Battles the Pink Robots, Pt. 1", "Face Down In The Gutter Of Your Love"} + user := User{Name: nulls.NewString("Patrik")} + + r.NoError(tx.Create(&user)) + r.NotZero(user.ID) + + count, err := tx.Count("songs") + r.NoError(err) + + for _, title := range songTitles { + err = tx.Create(&Song{Title: title, UserID: user.ID}) + r.NoError(err) + } + + ctx, err := tx.Count("songs") + r.NoError(err) + r.Equal(count+len(songTitles), ctx) + + err = tx.Where("u_id = ?", user.ID).Delete("songs") + r.NoError(err) + + ctx, err = tx.Count("songs") + r.NoError(err) + r.Equal(count, ctx) + }) +} diff --git a/query.go b/query.go index ba981ef5..3b20b5aa 100644 --- a/query.go +++ b/query.go @@ -7,6 +7,13 @@ import ( "github.com/gobuffalo/pop/v5/logging" ) +type operation string + +const ( + Select operation = "SELECT" + Delete operation = "DELETE" +) + // Query is the main value that is used to build up a query // to be executed against the `Connection`. type Query struct { @@ -25,6 +32,7 @@ type Query struct { havingClauses havingClauses Paginator *Paginator Connection *Connection + Operation operation } // Clone will fill targetQ query with the connection used in q, if @@ -42,6 +50,7 @@ func (q *Query) Clone(targetQ *Query) { targetQ.groupClauses = q.groupClauses targetQ.havingClauses = q.havingClauses targetQ.addColumns = q.addColumns + targetQ.Operation = q.Operation if q.Paginator != nil { paginator := *q.Paginator @@ -196,6 +205,7 @@ func Q(c *Connection) *Query { eager: c.eager, eagerFields: c.eagerFields, eagerMode: eagerModeNil, + Operation: Select, } } diff --git a/sql_builder.go b/sql_builder.go index b6e07223..b0b3c5b8 100644 --- a/sql_builder.go +++ b/sql_builder.go @@ -84,7 +84,14 @@ func (sq *sqlBuilder) compile() { sq.sql = sq.Query.RawSQL.Fragment } } else { - sq.sql = sq.buildSelectSQL() + switch sq.Query.Operation { + case Select: + sq.sql = sq.buildSelectSQL() + case Delete: + sq.sql = sq.buildDeleteSQL() + default: + panic("unexpected query operation " + sq.Query.Operation) + } } if inRegex.MatchString(sq.sql) { @@ -114,6 +121,27 @@ func (sq *sqlBuilder) buildSelectSQL() string { return sql } +func (sq *sqlBuilder) buildDeleteSQL() string { + fc := sq.buildfromClauses() + + sql := fmt.Sprintf("DELETE FROM %s", fc) + + sql = sq.buildWhereClauses(sql) + + // paginated delete supported by sqlite and mysql + // > If SQLite is compiled with the SQLITE_ENABLE_UPDATE_DELETE_LIMIT compile-time option [...] - from https://www.sqlite.org/lang_delete.html + // + // not generic enough IMO, therefore excluded + // + //switch sq.Query.Connection.Dialect.Name() { + //case nameMySQL, nameSQLite3: + // sql = sq.buildOrderClauses(sql) + // sql = sq.buildPaginationClauses(sql) + //} + + return sql +} + func (sq *sqlBuilder) buildfromClauses() fromClauses { models := []*Model{ sq.Model, diff --git a/test.sh b/test.sh index c6256045..4ea9a5f0 100755 --- a/test.sh +++ b/test.sh @@ -37,6 +37,11 @@ function cleanup { # defer cleanup, so it will be executed even after premature exit trap cleanup EXIT +# The cockroach volume is created by the root user if no user is set. +# Therefore we set the current user according to https://github.com/docker/compose/issues/1532#issuecomment-619548112 +CURRENT_UID="$(id -u):$(id -g)" +export CURRENT_UID + docker-compose up -d sleep 5 # Ensure mysql is online From bb7527ec9516feb0f9153d2a8505037d0d53a879 Mon Sep 17 00:00:00 2001 From: Patrik Date: Tue, 10 Aug 2021 08:54:48 +0200 Subject: [PATCH 23/59] Sort down migrations (#657) Basically, just reversing the up migration order does not work, as that puts "all" migrations before specific ones. Therefore, I added implemented the proper `Less` function for down migrations explicitly. Related #533 Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> --- file_migrator.go | 10 ++++- migration_box.go | 10 ++++- migration_box_test.go | 14 +++---- migration_info.go | 33 ++++++++++++---- migration_info_test.go | 88 ++++++++++++++++++++++++++---------------- migrator.go | 35 ++++++++--------- 6 files changed, 121 insertions(+), 69 deletions(-) diff --git a/file_migrator.go b/file_migrator.go index d4f0ec3e..271e71a6 100644 --- a/file_migrator.go +++ b/file_migrator.go @@ -81,7 +81,15 @@ func (fm *FileMigrator) findMigrations(runner func(mf Migration, tx *Connection) Type: match.Type, Runner: runner, } - fm.Migrations[mf.Direction] = append(fm.Migrations[mf.Direction], mf) + switch mf.Direction { + case "up": + fm.UpMigrations.Migrations = append(fm.UpMigrations.Migrations, mf) + case "down": + fm.DownMigrations.Migrations = append(fm.DownMigrations.Migrations, mf) + default: + // the regex only matches `(up|down)` for direction, so a panic here is appropriate + panic("got unknown migration direction " + mf.Direction) + } } return nil }) diff --git a/migration_box.go b/migration_box.go index 1e7d97ab..0385cc1d 100644 --- a/migration_box.go +++ b/migration_box.go @@ -75,7 +75,15 @@ func (fm *MigrationBox) findMigrations(runner func(f packd.File) func(mf Migrati Type: match.Type, Runner: runner(f), } - fm.Migrations[mf.Direction] = append(fm.Migrations[mf.Direction], mf) + switch mf.Direction { + case "up": + fm.UpMigrations.Migrations = append(fm.UpMigrations.Migrations, mf) + case "down": + fm.DownMigrations.Migrations = append(fm.DownMigrations.Migrations, mf) + default: + // the regex only matches `(up|down)` for direction, so a panic here is appropriate + panic("got unknown migration direction " + mf.Direction) + } return nil }) } diff --git a/migration_box_test.go b/migration_box_test.go index e094077b..7a9ada42 100644 --- a/migration_box_test.go +++ b/migration_box_test.go @@ -32,11 +32,11 @@ func Test_MigrationBox(t *testing.T) { b, err := NewMigrationBox(packr.New("./testdata/migrations/multiple", "./testdata/migrations/multiple"), PDB) r.NoError(err) - r.Equal(4, len(b.Migrations["up"])) - r.Equal("mysql", b.Migrations["up"][0].DBType) - r.Equal("postgres", b.Migrations["up"][1].DBType) - r.Equal("sqlite3", b.Migrations["up"][2].DBType) - r.Equal("all", b.Migrations["up"][3].DBType) + r.Equal(4, len(b.UpMigrations.Migrations)) + r.Equal("mysql", b.UpMigrations.Migrations[0].DBType) + r.Equal("postgres", b.UpMigrations.Migrations[1].DBType) + r.Equal("sqlite3", b.UpMigrations.Migrations[2].DBType) + r.Equal("all", b.UpMigrations.Migrations[3].DBType) }) t.Run("ignores clutter files", func(t *testing.T) { @@ -45,7 +45,7 @@ func Test_MigrationBox(t *testing.T) { b, err := NewMigrationBox(packr.New("./testdata/migrations/cluttered", "./testdata/migrations/cluttered"), PDB) r.NoError(err) - r.Equal(1, len(b.Migrations["up"])) + r.Equal(1, len(b.UpMigrations.Migrations)) r.Equal(1, len(*logs)) r.Equal(logging.Warn, (*logs)[0].lvl) r.Contains((*logs)[0].s, "ignoring file") @@ -58,7 +58,7 @@ func Test_MigrationBox(t *testing.T) { b, err := NewMigrationBox(packr.New("./testdata/migrations/unsupported_dialect", "./testdata/migrations/unsupported_dialect"), PDB) r.NoError(err) - r.Equal(0, len(b.Migrations["up"])) + r.Equal(0, len(b.UpMigrations.Migrations)) r.Equal(1, len(*logs)) r.Equal(logging.Warn, (*logs)[0].lvl) r.Contains((*logs)[0].s, "ignoring migration") diff --git a/migration_info.go b/migration_info.go index 3e6d5ce5..0fa26b14 100644 --- a/migration_info.go +++ b/migration_info.go @@ -36,14 +36,6 @@ func (mfs Migrations) Len() int { return len(mfs) } -func (mfs Migrations) Less(i, j int) bool { - if mfs[i].Version == mfs[j].Version { - // force "all" to the back - return mfs[i].DBType != "all" - } - return mfs[i].Version < mfs[j].Version -} - func (mfs Migrations) Swap(i, j int) { mfs[i], mfs[j] = mfs[j], mfs[i] } @@ -57,3 +49,28 @@ func (mfs *Migrations) Filter(f func(mf Migration) bool) { } *mfs = vsf } + +type ( + UpMigrations struct { + Migrations + } + DownMigrations struct { + Migrations + } +) + +func (mfs UpMigrations) Less(i, j int) bool { + if mfs.Migrations[i].Version == mfs.Migrations[j].Version { + // force "all" to the back + return mfs.Migrations[i].DBType != "all" + } + return mfs.Migrations[i].Version < mfs.Migrations[j].Version +} + +func (mfs DownMigrations) Less(i, j int) bool { + if mfs.Migrations[i].Version == mfs.Migrations[j].Version { + // force "all" to the back + return mfs.Migrations[i].DBType != "all" + } + return mfs.Migrations[i].Version > mfs.Migrations[j].Version +} diff --git a/migration_info_test.go b/migration_info_test.go index f2174551..fd86c64b 100644 --- a/migration_info_test.go +++ b/migration_info_test.go @@ -8,43 +8,65 @@ import ( ) func TestSortingMigrations(t *testing.T) { - t.Run("case=enforces precedence for specific migrations", func(t *testing.T) { - migrations := Migrations{ - { - Version: "1", - DBType: "all", - }, - { - Version: "1", - DBType: "postgres", - }, - { - Version: "2", - DBType: "cockroach", - }, - { - Version: "2", - DBType: "all", - }, - { - Version: "3", - DBType: "all", - }, - { - Version: "3", - DBType: "mysql", - }, + examples := Migrations{ + { + Version: "1", + DBType: "all", + }, + { + Version: "1", + DBType: "postgres", + }, + { + Version: "2", + DBType: "cockroach", + }, + { + Version: "2", + DBType: "all", + }, + { + Version: "3", + DBType: "all", + }, + { + Version: "3", + DBType: "mysql", + }, + } + + t.Run("case=enforces precedence for specific up migrations", func(t *testing.T) { + migrations := make(Migrations, len(examples)) + copy(migrations, examples) + + expectedOrder := Migrations{ + examples[1], + examples[0], + examples[2], + examples[3], + examples[5], + examples[4], } + + sort.Sort(UpMigrations{migrations}) + + assert.Equal(t, expectedOrder, migrations) + }) + + t.Run("case=enforces precedence for specific down migrations", func(t *testing.T) { + migrations := make(Migrations, len(examples)) + copy(migrations, examples) + expectedOrder := Migrations{ - migrations[1], - migrations[0], - migrations[2], - migrations[3], - migrations[5], - migrations[4], + examples[5], + examples[4], + examples[2], + examples[3], + examples[1], + examples[0], } - sort.Sort(migrations) + sort.Sort(DownMigrations{migrations}) assert.Equal(t, expectedOrder, migrations) }) diff --git a/migrator.go b/migrator.go index 6e3abdfc..39e19447 100644 --- a/migrator.go +++ b/migrator.go @@ -23,10 +23,6 @@ var mrx = regexp.MustCompile(`^(\d+)_([^.]+)(\.[a-z0-9]+)?\.(up|down)\.(sql|fizz func NewMigrator(c *Connection) Migrator { return Migrator{ Connection: c, - Migrations: map[string]Migrations{ - "up": {}, - "down": {}, - }, } } @@ -35,9 +31,10 @@ func NewMigrator(c *Connection) Migrator { // When building a new migration system, you should embed this // type into your migrator. type Migrator struct { - Connection *Connection - SchemaPath string - Migrations map[string]Migrations + Connection *Connection + SchemaPath string + UpMigrations UpMigrations + DownMigrations DownMigrations } func (m Migrator) migrationIsCompatible(d dialect, mi Migration) bool { @@ -53,10 +50,10 @@ func (m Migrator) UpLogOnly() error { c := m.Connection return m.exec(func() error { mtn := c.MigrationTableName() - mfs := m.Migrations["up"] + mfs := m.UpMigrations sort.Sort(mfs) return c.Transaction(func(tx *Connection) error { - for _, mi := range mfs { + for _, mi := range mfs.Migrations { if !m.migrationIsCompatible(c.Dialect, mi) { continue } @@ -89,12 +86,12 @@ func (m Migrator) UpTo(step int) (applied int, err error) { c := m.Connection err = m.exec(func() error { mtn := c.MigrationTableName() - mfs := m.Migrations["up"] + mfs := m.UpMigrations mfs.Filter(func(mf Migration) bool { return m.migrationIsCompatible(c.Dialect, mf) }) sort.Sort(mfs) - for _, mi := range mfs { + for _, mi := range mfs.Migrations { exists, err := c.Where("version = ?", mi.Version).Exists(mtn) if err != nil { return errors.Wrapf(err, "problem checking for migration version %s", mi.Version) @@ -139,20 +136,20 @@ func (m Migrator) Down(step int) error { if err != nil { return errors.Wrap(err, "migration down: unable count existing migration") } - mfs := m.Migrations["down"] + mfs := m.DownMigrations mfs.Filter(func(mf Migration) bool { return m.migrationIsCompatible(c.Dialect, mf) }) - sort.Sort(sort.Reverse(mfs)) + sort.Sort(mfs) // skip all ran migration - if len(mfs) > count { - mfs = mfs[len(mfs)-count:] + if len(mfs.Migrations) > count { + mfs.Migrations = mfs.Migrations[len(mfs.Migrations)-count:] } // run only required steps - if step > 0 && len(mfs) >= step { - mfs = mfs[:step] + if step > 0 && len(mfs.Migrations) >= step { + mfs.Migrations = mfs.Migrations[:step] } - for _, mi := range mfs { + for _, mi := range mfs.Migrations { exists, err := c.Where("version = ?", mi.Version).Exists(mtn) if err != nil { return errors.Wrapf(err, "problem checking for migration version %s", mi.Version) @@ -228,7 +225,7 @@ func (m Migrator) Status(out io.Writer) error { } w := tabwriter.NewWriter(out, 0, 0, 3, ' ', tabwriter.TabIndent) _, _ = fmt.Fprintln(w, "Version\tName\tStatus\t") - for _, mf := range m.Migrations["up"] { + for _, mf := range m.UpMigrations.Migrations { exists, err := m.Connection.Where("version = ?", mf.Version).Exists(m.Connection.MigrationTableName()) if err != nil { return errors.Wrapf(err, "problem with migration") From e38398334242f7659130b220434681018e1836c3 Mon Sep 17 00:00:00 2001 From: karlhaas Date: Sun, 3 Oct 2021 09:38:08 +0200 Subject: [PATCH 24/59] Preserve eager information when validating models (#664) (#665) Co-authored-by: Karl Haas --- executors.go | 6 ++++++ pop_test.go | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/executors.go b/executors.go index eaae29eb..0e78a3bf 100644 --- a/executors.go +++ b/executors.go @@ -97,6 +97,10 @@ func (c *Connection) Save(model interface{}, excludeColumns ...string) error { // If model is a slice, each item of the slice is validated then created in the database. func (c *Connection) ValidateAndCreate(model interface{}, excludeColumns ...string) (*validate.Errors, error) { sm := NewModel(model, c.Context()) + + isEager := c.eager + hasEagerFields := c.eagerFields + if err := sm.beforeValidate(c); err != nil { return nil, err } @@ -155,6 +159,8 @@ func (c *Connection) ValidateAndCreate(model interface{}, excludeColumns ...stri } } + c.eager = isEager + c.eagerFields = hasEagerFields return verrs, c.Create(model, excludeColumns...) } diff --git a/pop_test.go b/pop_test.go index 107ec86d..8aa74178 100644 --- a/pop_test.go +++ b/pop_test.go @@ -155,6 +155,10 @@ type Taxis []Taxi // Validate gets run every time you call a "Validate*" (ValidateAndSave, ValidateAndCreate, ValidateAndUpdate) method. // This method is not required and may be deleted. func (b *Book) Validate(tx *Connection) (*validate.Errors, error) { + // Execute another query to test if Validate causes eager creation to fail + if err := tx.All(&Taxis{}); err != nil { + return nil, err + } return validate.Validate( &validators.StringIsPresent{Field: b.Description, Name: "Description"}, ), nil From 45bb1708189037b1b13da626f11c34310513a31f Mon Sep 17 00:00:00 2001 From: Matthias Fasching Date: Tue, 23 Nov 2021 18:47:44 +0000 Subject: [PATCH 25/59] Migrate from packr to fs (#667) * Updating Pgx (#660) * adding goreleaser syntaz * updating pgx now really * Migrate from packr to fs * Migrate to v6 * Use old build tags * Update error handling * Fix error after rebase * Fix error handling * Fix filenames for embed Go 1.16 usage Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> --- .github/dependabot.yml | 11 + .github/workflows/release.yml | 23 +- .github/workflows/tests.yml | 142 +-- .golangci.yml | 2 +- Makefile | 5 - README.md | 2 +- SHOULDERS.md | 7 - associations/association.go | 2 +- associations/associations_for_struct.go | 2 +- associations/belongs_to_association.go | 4 +- associations/belongs_to_association_test.go | 2 +- associations/has_many_association_test.go | 2 +- associations/has_one_association.go | 2 +- associations/has_one_association_test.go | 2 +- associations/many_to_many_association.go | 2 +- associations/many_to_many_association_test.go | 2 +- columns/column_test.go | 2 +- columns/columns_test.go | 2 +- columns/readable_columns_test.go | 2 +- columns/tags_test.go | 3 +- columns/writeable_columns_test.go | 2 +- commands.go | 25 +- config.go | 14 +- config_test.go | 1 - connection.go | 36 +- connection_details.go | 13 +- connection_instrumented.go | 6 +- dialect.go | 2 +- dialect_cockroach.go | 26 +- dialect_common.go | 20 +- dialect_mysql.go | 50 +- dialect_postgresql.go | 27 +- dialect_sqlite.go | 46 +- executors.go | 12 +- executors_test.go | 1 + file_migrator.go | 8 +- finders.go | 13 +- fix/anko_test.go | 24 +- fix/auto_timestamps_off_test.go | 26 +- genny/config/config-packr.go | 8 - genny/config/config.go | 7 +- genny/config/config_test.go | 2 +- genny/config/options.go | 3 +- genny/fizz/cempty/options.go | 4 +- genny/fizz/ctable/create_table.go | 2 +- genny/fizz/ctable/options.go | 7 +- genny/model/_fixtures/models/widget.go | 2 +- genny/model/_fixtures/models/widget_empty.go | 2 +- .../model/_fixtures/models/widget_jsonapi.go | 2 +- genny/model/_fixtures/models/widget_xml.go | 2 +- genny/model/imports.go | 4 +- genny/model/model-packr.go | 8 - genny/model/model.go | 17 +- genny/model/model_test.go | 85 +- genny/model/options.go | 5 +- .../-name-.go.tmpl => path-/name-.go.tmpl} | 0 .../name-_test.go.tmpl} | 0 go.mod | 51 +- go.sum | 816 +++++++++++------- logger.go | 2 +- migration_box.go | 50 +- migration_box_test.go | 10 +- migration_content.go | 6 +- migrator.go | 35 +- model.go | 9 +- model_test.go | 10 +- packrd/packed-packr.go | 46 - paginator.go | 2 +- pop_test.go | 27 +- preload_associations.go | 4 +- query.go | 2 +- query_groups.go | 2 +- query_having.go | 2 +- query_joins.go | 2 +- slices/README.md | 14 +- slices_test.go | 2 +- soda/cmd/create.go | 2 +- soda/cmd/drop.go | 2 +- soda/cmd/fix.go | 2 +- soda/cmd/generate.go | 2 +- soda/cmd/generate/config_cmd.go | 6 +- soda/cmd/generate/fizz_cmd.go | 4 +- soda/cmd/generate/model_cmd.go | 6 +- soda/cmd/generate/sql_cmd.go | 6 +- soda/cmd/migrate.go | 3 +- soda/cmd/migrate_down.go | 2 +- soda/cmd/migrate_status.go | 2 +- soda/cmd/migrate_up.go | 2 +- soda/cmd/reset.go | 2 +- soda/cmd/root.go | 4 +- soda/cmd/schema.go | 2 +- soda/cmd/schema/dump.go | 2 +- soda/cmd/schema/load.go | 9 +- soda/main.go | 2 +- sql_builder.go | 4 +- tx.go | 7 +- 96 files changed, 1072 insertions(+), 824 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100644 genny/config/config-packr.go delete mode 100644 genny/model/model-packr.go rename genny/model/templates/{-path-/-name-.go.tmpl => path-/name-.go.tmpl} (100%) rename genny/model/templates/{-path-/-name-_test.go.tmpl => path-/name-_test.go.tmpl} (100%) delete mode 100644 packrd/packed-packr.go diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..aad738c7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "daily" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 08c77532..6063f897 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,25 +1,28 @@ name: Release - on: - create: - tags: - - v*.*.* + release: + types: + - published jobs: release: name: Release runs-on: ubuntu-latest - container: - image: bepsays/ci-goreleaser:1.15.1 steps: - - name: Checkout Code - uses: actions/checkout@master + - name: Set up Go 1.17 + uses: actions/setup-go@v2 with: - fetch-depth: 0 + go-version: 1.17 + id: go + + - name: Checkout Code + uses: actions/checkout@v2 + - name: Fetch tags run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* + - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v1 + uses: goreleaser/goreleaser-action@v2 env: GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN }} with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1e5f5583..99acfce1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,9 +1,19 @@ name: Tests -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + jobs: mysql-tests: - name: MySQL tests + name: MySQL tests - Go v${{ matrix.go-version }} runs-on: ubuntu-latest + strategy: + matrix: + go-version: + - "1.16.x" + - "1.17.x" services: mysql: @@ -16,18 +26,12 @@ jobs: options: --health-cmd "mysqladmin ping -h localhost" --health-interval 10s --health-timeout 5s --health-retries 5 steps: - - name: Set up Go - uses: actions/setup-go@v1 - with: - go-version: 1.15 - id: go - - name: Checkout Code - uses: actions/checkout@v1 + - uses: actions/checkout@v2 + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v2 with: - fetch-depth: 1 - - name: Get dependencies - run: | - go get -v -tags sqlite -t -d ./... + go-version: ${{ matrix.go-version }} + - name: Build and run soda env: SODA_DIALECT: "mysql" @@ -37,20 +41,26 @@ jobs: ./tsoda drop -e $SODA_DIALECT -p ./testdata/migrations ./tsoda create -e $SODA_DIALECT -p ./testdata/migrations ./tsoda migrate -e $SODA_DIALECT -p ./testdata/migrations + - name: Test env: SODA_DIALECT: "mysql" MYSQL_PORT: 3307 run: | - go test -tags sqlite -race ./... + go test -tags sqlite -race -cover ./... pg-tests: - name: PostgreSQL tests + name: PostgreSQL tests - Go v${{ matrix.go-version }} runs-on: ubuntu-latest + strategy: + matrix: + go-version: + - "1.16.x" + - "1.17.x" services: postgres: - image: postgres:10.8 + image: postgres:14 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres @@ -61,18 +71,12 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - - name: Set up Go - uses: actions/setup-go@v1 - with: - go-version: 1.15 - id: go - - name: Checkout Code - uses: actions/checkout@v1 + - uses: actions/checkout@v2 + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v2 with: - fetch-depth: 1 - - name: Get dependencies - run: | - go get -v -tags sqlite -t -d ./... + go-version: ${{ matrix.go-version }} + - name: Build and run soda env: SODA_DIALECT: "postgres" @@ -82,30 +86,30 @@ jobs: ./tsoda drop -e $SODA_DIALECT -p ./testdata/migrations ./tsoda create -e $SODA_DIALECT -p ./testdata/migrations ./tsoda migrate -e $SODA_DIALECT -p ./testdata/migrations + - name: Test env: SODA_DIALECT: "postgres" POSTGRESQL_URL: "postgres://postgres:postgres@127.0.0.1:${{ job.services.postgres.ports[5432] }}/pop_test?sslmode=disable" run: | - go test -tags sqlite -race ./... + go test -tags sqlite -race -cover ./... crdbssl-tests: - name: Cockroach SSL tests + name: Cockroach SSL tests - Go v${{ matrix.go-version }} runs-on: ubuntu-latest + strategy: + matrix: + go-version: + - "1.16.x" + - "1.17.x" steps: - - name: Set up Go - uses: actions/setup-go@v1 - with: - go-version: 1.15 - id: go - - name: Checkout Code - uses: actions/checkout@v1 + - uses: actions/checkout@v2 + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v2 with: - fetch-depth: 1 - - name: Get dependencies - run: | - go get -v -tags sqlite -t -d ./... + go-version: ${{ matrix.go-version }} + - name: Install Cockroach SSL run: | mkdir -p crdb/certs @@ -117,6 +121,7 @@ jobs: ./cockroach cert create-node localhost 127.0.0.1 `hostname -s` `hostname -f` --certs-dir certs --ca-key key ./cockroach start-single-node --certs-dir certs --listen-addr localhost --port 26259 --http-port 8089 --background popd + - name: Build and run soda env: SODA_DIALECT: "cockroach_ssl" @@ -125,29 +130,29 @@ jobs: ./tsoda drop -e $SODA_DIALECT -p ./testdata/migrations ./tsoda create -e $SODA_DIALECT -p ./testdata/migrations ./tsoda migrate -e $SODA_DIALECT -p ./testdata/migrations + - name: Test env: SODA_DIALECT: "cockroach_ssl" run: | - go test -tags sqlite -race ./... + go test -tags sqlite -race -cover ./... crdb-tests: name: Cockroach tests runs-on: ubuntu-latest + strategy: + matrix: + go-version: + - "1.16.x" + - "1.17.x" steps: - - name: Set up Go - uses: actions/setup-go@v1 + - uses: actions/checkout@v2 + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v2 with: - go-version: 1.15 - id: go - - name: Checkout Code - uses: actions/checkout@v1 - with: - fetch-depth: 1 - - name: Get dependencies - run: | - go get -v -tags sqlite -t -d ./... + go-version: ${{ matrix.go-version }} + - name: Install Cockroach run: | mkdir -p crdb @@ -156,6 +161,7 @@ jobs: mv cockroach-v20.2.4.linux-amd64/cockroach . ./cockroach start-single-node --insecure --background popd + - name: Build and run soda env: SODA_DIALECT: "cockroach" @@ -164,32 +170,33 @@ jobs: ./tsoda drop -e $SODA_DIALECT -p ./testdata/migrations ./tsoda create -e $SODA_DIALECT -p ./testdata/migrations ./tsoda migrate -e $SODA_DIALECT -p ./testdata/migrations + - name: Test env: SODA_DIALECT: "cockroach" run: | - go test -tags sqlite -race ./... + go test -tags sqlite -race -cover ./... sqlite-tests: - name: SQLite tests + name: SQLite tests ${{ matrix.os }} - Go v${{ matrix.go-version }} runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macOS-latest, windows-latest] + go-version: + - "1.16.x" + - "1.17.x" + os: + - "macos-latest" + - "windows-latest" + - "ubuntu-latest" steps: - - name: Set up Go - uses: actions/setup-go@v1 - with: - go-version: 1.15 - id: go - - name: Checkout Code - uses: actions/checkout@v1 + - uses: actions/checkout@v2 + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v2 with: - fetch-depth: 1 - - name: Get dependencies - run: | - go get -v -tags sqlite -t -d ./... + go-version: ${{ matrix.go-version }} + - name: Build and run soda env: SODA_DIALECT: "sqlite" @@ -199,8 +206,9 @@ jobs: ./tsoda create -e $SODA_DIALECT -p ./testdata/migrations ./tsoda migrate -e $SODA_DIALECT -p ./testdata/migrations shell: bash + - name: Test env: SODA_DIALECT: "sqlite" run: | - go test -tags sqlite -race ./... + go test -tags sqlite -race -cover ./... diff --git a/.golangci.yml b/.golangci.yml index f75e3546..c811d055 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,4 +13,4 @@ run: linters-settings: govet: # report about shadowed variables - check-shadowing: true \ No newline at end of file + check-shadowing: true diff --git a/Makefile b/Makefile index cc73115e..893e46e8 100644 --- a/Makefile +++ b/Makefile @@ -2,23 +2,19 @@ TAGS ?= "sqlite" GO_BIN ?= go install: deps - packr2 $(GO_BIN) install -tags ${TAGS} -v ./soda deps: $(GO_BIN) get github.com/gobuffalo/release - $(GO_BIN) get github.com/gobuffalo/packr/v2/packr2 $(GO_BIN) get -tags ${TAGS} -t ./... ifeq ($(GO111MODULE),on) $(GO_BIN) mod tidy endif build: - packr2 $(GO_BIN) build -v . test: - # packr2 $(GO_BIN) test -tags ${TAGS} ./... ci-test: @@ -32,7 +28,6 @@ update: ifeq ($(GO111MODULE),on) $(GO_BIN) mod tidy endif - packr2 make test make install ifeq ($(GO111MODULE),on) diff --git a/README.md b/README.md index 3b7bd5c9..8953c85a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- GoDoc + GoDoc Build Status

diff --git a/SHOULDERS.md b/SHOULDERS.md index 09bc3864..5c2380f3 100644 --- a/SHOULDERS.md +++ b/SHOULDERS.md @@ -4,7 +4,6 @@ Pop does not try to reinvent the wheel! Instead, it uses the already great wheel Thank you to the following **GIANTS**: - * [github.com/cockroachdb/apd](https://godoc.org/github.com/cockroachdb/apd) * [github.com/cockroachdb/cockroach-go](https://godoc.org/github.com/cockroachdb/cockroach-go) @@ -29,10 +28,6 @@ Thank you to the following **GIANTS**: * [github.com/gobuffalo/nulls](https://godoc.org/github.com/gobuffalo/nulls) -* [github.com/gobuffalo/packd](https://godoc.org/github.com/gobuffalo/packd) - -* [github.com/gobuffalo/packr/v2](https://godoc.org/github.com/gobuffalo/packr/v2) - * [github.com/gobuffalo/plush](https://godoc.org/github.com/gobuffalo/plush) * [github.com/gobuffalo/validate](https://godoc.org/github.com/gobuffalo/validate) @@ -55,8 +50,6 @@ Thank you to the following **GIANTS**: * [github.com/mattn/go-sqlite3](https://godoc.org/github.com/mattn/go-sqlite3) -* [github.com/pkg/errors](https://godoc.org/github.com/pkg/errors) - * [github.com/satori/go.uuid](https://godoc.org/github.com/satori/go.uuid) * [github.com/shopspring/decimal](https://godoc.org/github.com/shopspring/decimal) diff --git a/associations/association.go b/associations/association.go index 8fa335fd..436c4581 100644 --- a/associations/association.go +++ b/associations/association.go @@ -4,7 +4,7 @@ import ( "reflect" "github.com/gobuffalo/nulls" - "github.com/gobuffalo/pop/v5/columns" + "github.com/gobuffalo/pop/v6/columns" ) // Association represents a definition of a model association diff --git a/associations/associations_for_struct.go b/associations/associations_for_struct.go index 368e72c0..67c8ca76 100644 --- a/associations/associations_for_struct.go +++ b/associations/associations_for_struct.go @@ -7,7 +7,7 @@ import ( "regexp" "strings" - "github.com/gobuffalo/pop/v5/columns" + "github.com/gobuffalo/pop/v6/columns" ) // If a field match with the regexp, it will be considered as a valid field definition. diff --git a/associations/belongs_to_association.go b/associations/belongs_to_association.go index a28e5d0a..fce161d0 100644 --- a/associations/belongs_to_association.go +++ b/associations/belongs_to_association.go @@ -6,8 +6,8 @@ import ( "github.com/gobuffalo/flect" "github.com/gobuffalo/nulls" - "github.com/gobuffalo/pop/v5/columns" - "github.com/gobuffalo/pop/v5/internal/defaults" + "github.com/gobuffalo/pop/v6/columns" + "github.com/gobuffalo/pop/v6/internal/defaults" ) // belongsToAssociation is the implementation for the belongs_to association type in a model. diff --git a/associations/belongs_to_association_test.go b/associations/belongs_to_association_test.go index bf1abb30..f7a09ba3 100644 --- a/associations/belongs_to_association_test.go +++ b/associations/belongs_to_association_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/gobuffalo/pop/v5/associations" + "github.com/gobuffalo/pop/v6/associations" "github.com/gofrs/uuid" "github.com/stretchr/testify/require" ) diff --git a/associations/has_many_association_test.go b/associations/has_many_association_test.go index 1c428ca4..6028b9b6 100644 --- a/associations/has_many_association_test.go +++ b/associations/has_many_association_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gobuffalo/nulls" - "github.com/gobuffalo/pop/v5/associations" + "github.com/gobuffalo/pop/v6/associations" "github.com/stretchr/testify/require" ) diff --git a/associations/has_one_association.go b/associations/has_one_association.go index e708eefe..da80d7d3 100644 --- a/associations/has_one_association.go +++ b/associations/has_one_association.go @@ -6,7 +6,7 @@ import ( "github.com/gobuffalo/flect" "github.com/gobuffalo/nulls" - "github.com/gobuffalo/pop/v5/internal/defaults" + "github.com/gobuffalo/pop/v6/internal/defaults" ) // hasOneAssociation is a 1 to 1 kind of association. It's used on diff --git a/associations/has_one_association_test.go b/associations/has_one_association_test.go index 169c5889..8eacd074 100644 --- a/associations/has_one_association_test.go +++ b/associations/has_one_association_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gobuffalo/nulls" - "github.com/gobuffalo/pop/v5/associations" + "github.com/gobuffalo/pop/v6/associations" "github.com/gofrs/uuid" "github.com/stretchr/testify/require" ) diff --git a/associations/many_to_many_association.go b/associations/many_to_many_association.go index e9bd8d57..2046e791 100644 --- a/associations/many_to_many_association.go +++ b/associations/many_to_many_association.go @@ -6,7 +6,7 @@ import ( "time" "github.com/gobuffalo/flect" - "github.com/gobuffalo/pop/v5/internal/defaults" + "github.com/gobuffalo/pop/v6/internal/defaults" "github.com/gofrs/uuid" ) diff --git a/associations/many_to_many_association_test.go b/associations/many_to_many_association_test.go index 0c8a97af..99fee4d8 100644 --- a/associations/many_to_many_association_test.go +++ b/associations/many_to_many_association_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/gobuffalo/pop/v5/associations" + "github.com/gobuffalo/pop/v6/associations" "github.com/gofrs/uuid" "github.com/stretchr/testify/require" ) diff --git a/columns/column_test.go b/columns/column_test.go index 860a4d03..4f6ee20a 100644 --- a/columns/column_test.go +++ b/columns/column_test.go @@ -3,7 +3,7 @@ package columns_test import ( "testing" - "github.com/gobuffalo/pop/v5/columns" + "github.com/gobuffalo/pop/v6/columns" "github.com/stretchr/testify/require" ) diff --git a/columns/columns_test.go b/columns/columns_test.go index f4699dc4..22101b34 100644 --- a/columns/columns_test.go +++ b/columns/columns_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/gobuffalo/pop/v5/columns" + "github.com/gobuffalo/pop/v6/columns" "github.com/stretchr/testify/require" ) diff --git a/columns/readable_columns_test.go b/columns/readable_columns_test.go index a563d789..2b6fb26a 100644 --- a/columns/readable_columns_test.go +++ b/columns/readable_columns_test.go @@ -3,7 +3,7 @@ package columns_test import ( "testing" - "github.com/gobuffalo/pop/v5/columns" + "github.com/gobuffalo/pop/v6/columns" "github.com/stretchr/testify/require" ) diff --git a/columns/tags_test.go b/columns/tags_test.go index 993cbcc4..a19c0e5e 100644 --- a/columns/tags_test.go +++ b/columns/tags_test.go @@ -4,8 +4,7 @@ import ( "reflect" "testing" - "github.com/gobuffalo/pop/v5/columns" - + "github.com/gobuffalo/pop/v6/columns" "github.com/stretchr/testify/require" ) diff --git a/columns/writeable_columns_test.go b/columns/writeable_columns_test.go index 053dbdaf..9998f625 100644 --- a/columns/writeable_columns_test.go +++ b/columns/writeable_columns_test.go @@ -3,7 +3,7 @@ package columns_test import ( "testing" - "github.com/gobuffalo/pop/v5/columns" + "github.com/gobuffalo/pop/v6/columns" "github.com/stretchr/testify/require" ) diff --git a/commands.go b/commands.go index 4d69cb6f..0b21ce88 100644 --- a/commands.go +++ b/commands.go @@ -3,16 +3,20 @@ package pop import ( "fmt" - "github.com/gobuffalo/pop/v5/logging" - "github.com/pkg/errors" + "github.com/gobuffalo/pop/v6/logging" ) // CreateDB creates a database, given a connection definition func CreateDB(c *Connection) error { deets := c.Dialect.Details() - if deets.Database != "" { - log(logging.Info, fmt.Sprintf("create %s (%s)", deets.Database, c.URL())) - return errors.Wrapf(c.Dialect.CreateDB(), "couldn't create database %s", deets.Database) + if deets.Database == "" { + return nil + } + + log(logging.Info, fmt.Sprintf("create %s (%s)", deets.Database, c.URL())) + + if err := c.Dialect.CreateDB(); err != nil { + return fmt.Errorf("couldn't create database %s: %w", deets.Database, err) } return nil } @@ -20,9 +24,14 @@ func CreateDB(c *Connection) error { // DropDB drops an existing database, given a connection definition func DropDB(c *Connection) error { deets := c.Dialect.Details() - if deets.Database != "" { - log(logging.Info, fmt.Sprintf("drop %s (%s)", deets.Database, c.URL())) - return errors.Wrapf(c.Dialect.DropDB(), "couldn't drop database %s", deets.Database) + if deets.Database == "" { + return nil + } + + log(logging.Info, fmt.Sprintf("drop %s (%s)", deets.Database, c.URL())) + + if err := c.Dialect.DropDB(); err != nil { + return fmt.Errorf("couldn't drop database %s: %w", deets.Database, err) } return nil } diff --git a/config.go b/config.go index 0e818e16..5d2d6498 100644 --- a/config.go +++ b/config.go @@ -2,6 +2,8 @@ package pop import ( "bytes" + "errors" + "fmt" "io" "io/ioutil" "os" @@ -9,8 +11,7 @@ import ( "text/template" "github.com/gobuffalo/envy" - "github.com/gobuffalo/pop/v5/logging" - "github.com/pkg/errors" + "github.com/gobuffalo/pop/v6/logging" "gopkg.in/yaml.v2" ) @@ -109,16 +110,19 @@ func ParseConfig(r io.Reader) (map[string]*ConnectionDetails, error) { } t, err := tmpl.Parse(string(b)) if err != nil { - return nil, errors.Wrap(err, "couldn't parse config template") + return nil, fmt.Errorf("couldn't parse config template: %w", err) } var bb bytes.Buffer err = t.Execute(&bb, nil) if err != nil { - return nil, errors.Wrap(err, "couldn't execute config template") + return nil, fmt.Errorf("couldn't execute config template: %w", err) } deets := map[string]*ConnectionDetails{} err = yaml.Unmarshal(bb.Bytes(), &deets) - return deets, errors.Wrap(err, "couldn't unmarshal config to yaml") + if err != nil { + return nil, fmt.Errorf("couldn't unmarshal config to yaml: %w", err) + } + return deets, nil } diff --git a/config_test.go b/config_test.go index 9ac0c78b..58d20a1a 100644 --- a/config_test.go +++ b/config_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/gobuffalo/envy" - "github.com/stretchr/testify/require" ) diff --git a/connection.go b/connection.go index 91d299bd..f8b81d31 100644 --- a/connection.go +++ b/connection.go @@ -2,13 +2,13 @@ package pop import ( "context" + "errors" + "fmt" "sync/atomic" "time" - "github.com/pkg/errors" - - "github.com/gobuffalo/pop/v5/internal/defaults" - "github.com/gobuffalo/pop/v5/internal/randx" + "github.com/gobuffalo/pop/v6/internal/defaults" + "github.com/gobuffalo/pop/v6/internal/randx" ) // Connections contains all available connections @@ -68,11 +68,11 @@ func NewConnection(deets *ConnectionDetails) (*Connection, error) { if nc, ok := newConnection[deets.Dialect]; ok { c.Dialect, err = nc(deets) if err != nil { - return c, errors.Wrap(err, "could not create new connection") + return c, fmt.Errorf("could not create new connection: %w", err) } return c, nil } - return nil, errors.Errorf("could not found connection creator for %v", deets.Dialect) + return nil, fmt.Errorf("could not found connection creator for %v", deets.Dialect) } // Connect takes the name of a connection, default is "development", and will @@ -90,10 +90,13 @@ func Connect(e string) (*Connection, error) { e = defaults.String(e, "development") c := Connections[e] if c == nil { - return c, errors.Errorf("could not find connection named %s", e) + return c, fmt.Errorf("could not find connection named %s", e) + } + + if err := c.Open(); err != nil { + return c, fmt.Errorf("couldn't open connection for %s: %w", e, err) } - err := c.Open() - return c, errors.Wrapf(err, "couldn't open connection for %s", e) + return c, nil } // Open creates a new datasource connection @@ -127,17 +130,20 @@ func (c *Connection) Open() error { c.Store = &dB{db} if d, ok := c.Dialect.(afterOpenable); ok { - err = d.AfterOpen(c) - if err != nil { + if err := d.AfterOpen(c); err != nil { c.Store = nil + return fmt.Errorf("could not open database connection: %w", err) } } - return errors.Wrap(err, "could not open database connection") + return nil } // Close destroys an active datasource connection func (c *Connection) Close() error { - return errors.Wrap(c.Store.Close(), "couldn't close connection") + if err := c.Store.Close(); err != nil { + return fmt.Errorf("couldn't close connection: %w", err) + } + return nil } // Transaction will start a new transaction on the connection. If the inner function @@ -158,7 +164,7 @@ func (c *Connection) Transaction(fn func(tx *Connection) error) error { } if dberr != nil { - return errors.Wrap(dberr, "error committing or rolling back transaction") + return fmt.Errorf("error committing or rolling back transaction: %w", dberr) } return err @@ -183,7 +189,7 @@ func (c *Connection) NewTransaction() (*Connection, error) { if c.TX == nil { tx, err := c.Store.Transaction() if err != nil { - return cn, errors.Wrap(err, "couldn't start a new transaction") + return cn, fmt.Errorf("couldn't start a new transaction: %w", err) } var store store = tx diff --git a/connection_details.go b/connection_details.go index d7a7ff37..50c2fe4b 100644 --- a/connection_details.go +++ b/connection_details.go @@ -1,6 +1,7 @@ package pop import ( + "errors" "fmt" "net/url" "regexp" @@ -8,11 +9,9 @@ import ( "strings" "time" + "github.com/gobuffalo/pop/v6/internal/defaults" + "github.com/gobuffalo/pop/v6/logging" "github.com/luna-duclos/instrumentedsql" - - "github.com/gobuffalo/pop/v5/internal/defaults" - "github.com/gobuffalo/pop/v5/logging" - "github.com/pkg/errors" ) // ConnectionDetails stores the data needed to connect to a datasource @@ -88,7 +87,7 @@ func (cd *ConnectionDetails) withURL() error { } if !DialectSupported(cd.Dialect) { - return errors.Errorf("unsupported dialect '%s'", cd.Dialect) + return fmt.Errorf("unsupported dialect '%s'", cd.Dialect) } // warning message is required to prevent confusion @@ -104,7 +103,7 @@ func (cd *ConnectionDetails) withURL() error { // Fallback on generic parsing if no URL parser was found for the dialect. u, err := url.Parse(ul) if err != nil { - return errors.Wrapf(err, "couldn't parse %s", ul) + return fmt.Errorf("couldn't parse %s: %w", ul, err) } cd.Database = strings.TrimPrefix(u.Path, "/") @@ -149,7 +148,7 @@ func (cd *ConnectionDetails) Finalize() error { } return errors.New("no database or URL specified") } - return errors.Errorf("unsupported dialect '%v'", cd.Dialect) + return fmt.Errorf("unsupported dialect '%v'", cd.Dialect) } // RetrySleep returns the amount of time to wait between two connection retries diff --git a/connection_instrumented.go b/connection_instrumented.go index f2d46b02..0118e848 100644 --- a/connection_instrumented.go +++ b/connection_instrumented.go @@ -3,13 +3,13 @@ package pop import ( "database/sql" "database/sql/driver" + "fmt" mysqld "github.com/go-sql-driver/mysql" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/logging" pgx "github.com/jackc/pgx/v4/stdlib" "github.com/jmoiron/sqlx" "github.com/luna-duclos/instrumentedsql" - "github.com/pkg/errors" ) const instrumentedDriverName = "instrumented-sql-driver" @@ -85,7 +85,7 @@ func openPotentiallyInstrumentedConnection(c dialect, dsn string) (*sqlx.DB, err con, err := sql.Open(driverName, dsn) if err != nil { - return nil, errors.Wrap(err, "could not open database connection") + return nil, fmt.Errorf("could not open database connection: %w", err) } return sqlx.NewDb(con, dialect), nil diff --git a/dialect.go b/dialect.go index 4ff29a3b..1b87847d 100644 --- a/dialect.go +++ b/dialect.go @@ -4,7 +4,7 @@ import ( "io" "github.com/gobuffalo/fizz" - "github.com/gobuffalo/pop/v5/columns" + "github.com/gobuffalo/pop/v6/columns" ) type crudable interface { diff --git a/dialect_cockroach.go b/dialect_cockroach.go index 5d200d65..2ea10cb3 100644 --- a/dialect_cockroach.go +++ b/dialect_cockroach.go @@ -9,16 +9,13 @@ import ( "strings" "sync" - // Import PostgreSQL driver - _ "github.com/jackc/pgx/v4/stdlib" - "github.com/gobuffalo/fizz" "github.com/gobuffalo/fizz/translators" - "github.com/gobuffalo/pop/v5/columns" - "github.com/gobuffalo/pop/v5/internal/defaults" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/columns" + "github.com/gobuffalo/pop/v6/internal/defaults" + "github.com/gobuffalo/pop/v6/logging" + _ "github.com/jackc/pgx/v4/stdlib" // Import PostgreSQL driver "github.com/jmoiron/sqlx" - "github.com/pkg/errors" ) const nameCockroach = "cockroach" @@ -90,12 +87,15 @@ func (p *cockroach) Create(s store, model *Model, cols columns.Columns) error { err = stmt.QueryRow(model.Value).MapScan(id) if err != nil { if closeErr := stmt.Close(); closeErr != nil { - return errors.Wrapf(err, "failed to close prepared statement: %s", closeErr) + return fmt.Errorf("failed to close prepared statement: %s: %w", closeErr, err) } return err } model.setID(id[model.IDField()]) - return errors.WithMessage(stmt.Close(), "failed to close statement") + if err := stmt.Close(); err != nil { + return fmt.Errorf("failed to close statement: %w", err) + } + return nil } return genericCreate(s, model, cols, p) } @@ -128,7 +128,7 @@ func (p *cockroach) CreateDB() error { db, err := openPotentiallyInstrumentedConnection(p, p.urlWithoutDb()) if err != nil { - return errors.Wrapf(err, "error creating Cockroach database %s", deets.Database) + return fmt.Errorf("error creating Cockroach database %s: %w", deets.Database, err) } defer db.Close() query := fmt.Sprintf("CREATE DATABASE %s", p.Quote(deets.Database)) @@ -136,7 +136,7 @@ func (p *cockroach) CreateDB() error { _, err = db.Exec(query) if err != nil { - return errors.Wrapf(err, "error creating Cockroach database %s", deets.Database) + return fmt.Errorf("error creating Cockroach database %s: %w", deets.Database, err) } log(logging.Info, "created database %s", deets.Database) @@ -148,7 +148,7 @@ func (p *cockroach) DropDB() error { db, err := openPotentiallyInstrumentedConnection(p, p.urlWithoutDb()) if err != nil { - return errors.Wrapf(err, "error dropping Cockroach database %s", deets.Database) + return fmt.Errorf("error dropping Cockroach database %s: %w", deets.Database, err) } defer db.Close() query := fmt.Sprintf("DROP DATABASE %s CASCADE;", p.Quote(deets.Database)) @@ -156,7 +156,7 @@ func (p *cockroach) DropDB() error { _, err = db.Exec(query) if err != nil { - return errors.Wrapf(err, "error dropping Cockroach database %s", deets.Database) + return fmt.Errorf("error dropping Cockroach database %s: %w", deets.Database, err) } log(logging.Info, "dropped database %s", deets.Database) diff --git a/dialect_common.go b/dialect_common.go index 5a9eee9c..00e9e552 100644 --- a/dialect_common.go +++ b/dialect_common.go @@ -11,10 +11,9 @@ import ( "os/exec" "strings" - "github.com/gobuffalo/pop/v5/columns" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/columns" + "github.com/gobuffalo/pop/v6/logging" "github.com/gofrs/uuid" - "github.com/pkg/errors" ) func init() { @@ -89,13 +88,16 @@ func genericCreate(s store, model *Model, cols columns.Columns, quoter quotable) _, err = stmt.Exec(model.Value) if err != nil { if closeErr := stmt.Close(); closeErr != nil { - return errors.Wrapf(err, "failed to close prepared statement: %s", closeErr) + return fmt.Errorf("failed to close prepared statement: %s: %w", closeErr, err) } return err } - return errors.WithMessage(stmt.Close(), "failed to close statement") + if err := stmt.Close(); err != nil { + return fmt.Errorf("failed to close statement: %w", err) + } + return nil } - return errors.Errorf("can not use %s as a primary key type!", keyType) + return fmt.Errorf("can not use %s as a primary key type!", keyType) } func genericUpdate(s store, model *Model, cols columns.Columns, quoter quotable) error { @@ -155,7 +157,7 @@ func genericLoadSchema(d dialect, r io.Reader) error { // Open DB connection on the target DB db, err := openPotentiallyInstrumentedConnection(d, d.MigrationURL()) if err != nil { - return errors.WithMessage(err, fmt.Sprintf("unable to load schema for %s", deets.Database)) + return fmt.Errorf("unable to load schema for %s: %w", deets.Database, err) } defer db.Close() @@ -172,7 +174,7 @@ func genericLoadSchema(d dialect, r io.Reader) error { _, err = db.Exec(string(contents)) if err != nil { - return errors.WithMessage(err, fmt.Sprintf("unable to load schema for %s", deets.Database)) + return fmt.Errorf("unable to load schema for %s: %w", deets.Database, err) } log(logging.Info, "loaded schema for %s", deets.Database) @@ -195,7 +197,7 @@ func genericDumpSchema(deets *ConnectionDetails, cmd *exec.Cmd, w io.Writer) err x := bytes.TrimSpace(bb.Bytes()) if len(x) == 0 { - return errors.Errorf("unable to dump schema for %s", deets.Database) + return fmt.Errorf("unable to dump schema for %s", deets.Database) } log(logging.Info, "dumped schema for %s", deets.Database) diff --git a/dialect_mysql.go b/dialect_mysql.go index dbd9b49b..1cfda3cf 100644 --- a/dialect_mysql.go +++ b/dialect_mysql.go @@ -7,14 +7,12 @@ import ( "os/exec" "strings" - // Load MySQL Go driver - _mysql "github.com/go-sql-driver/mysql" + _mysql "github.com/go-sql-driver/mysql" // Load MySQL Go driver "github.com/gobuffalo/fizz" "github.com/gobuffalo/fizz/translators" - "github.com/gobuffalo/pop/v5/columns" - "github.com/gobuffalo/pop/v5/internal/defaults" - "github.com/gobuffalo/pop/v5/logging" - "github.com/pkg/errors" + "github.com/gobuffalo/pop/v6/columns" + "github.com/gobuffalo/pop/v6/internal/defaults" + "github.com/gobuffalo/pop/v6/logging" ) const nameMySQL = "mysql" @@ -83,17 +81,26 @@ func (m *mysql) MigrationURL() string { } func (m *mysql) Create(s store, model *Model, cols columns.Columns) error { - return errors.Wrap(genericCreate(s, model, cols, m), "mysql create") + if err := genericCreate(s, model, cols, m); err != nil { + return fmt.Errorf("mysql create: %w", err) + } + return nil } func (m *mysql) Update(s store, model *Model, cols columns.Columns) error { - return errors.Wrap(genericUpdate(s, model, cols, m), "mysql update") + if err := genericUpdate(s, model, cols, m); err != nil { + return fmt.Errorf("mysql update: %w", err) + } + return nil } func (m *mysql) Destroy(s store, model *Model) error { stmt := fmt.Sprintf("DELETE FROM %s WHERE %s = ?", m.Quote(model.TableName()), model.IDField()) _, err := genericExec(s, stmt, model.ID()) - return errors.Wrap(err, "mysql destroy") + if err != nil { + return fmt.Errorf("mysql destroy: %w", err) + } + return nil } func (m *mysql) Delete(s store, model *Model, query Query) error { @@ -103,15 +110,24 @@ func (m *mysql) Delete(s store, model *Model, query Query) error { sql = sb.buildWhereClauses(sql) _, err := genericExec(s, sql, sb.Args()...) - return errors.Wrap(err, "mysql delete") + if err != nil { + return fmt.Errorf("mysql delete: %w", err) + } + return nil } func (m *mysql) SelectOne(s store, model *Model, query Query) error { - return errors.Wrap(genericSelectOne(s, model, query), "mysql select one") + if err := genericSelectOne(s, model, query); err != nil { + return fmt.Errorf("mysql select one: %w", err) + } + return nil } func (m *mysql) SelectMany(s store, models *Model, query Query) error { - return errors.Wrap(genericSelectMany(s, models, query), "mysql select many") + if err := genericSelectMany(s, models, query); err != nil { + return fmt.Errorf("mysql select many: %w", err) + } + return nil } // CreateDB creates a new database, from the given connection credentials @@ -119,7 +135,7 @@ func (m *mysql) CreateDB() error { deets := m.ConnectionDetails db, err := openPotentiallyInstrumentedConnection(m, m.urlWithoutDb()) if err != nil { - return errors.Wrapf(err, "error creating MySQL database %s", deets.Database) + return fmt.Errorf("error creating MySQL database %s: %w", deets.Database, err) } defer db.Close() charset := defaults.String(deets.Options["charset"], "utf8mb4") @@ -129,7 +145,7 @@ func (m *mysql) CreateDB() error { _, err = db.Exec(query) if err != nil { - return errors.Wrapf(err, "error creating MySQL database %s", deets.Database) + return fmt.Errorf("error creating MySQL database %s: %w", deets.Database, err) } log(logging.Info, "created database %s", deets.Database) @@ -141,7 +157,7 @@ func (m *mysql) DropDB() error { deets := m.ConnectionDetails db, err := openPotentiallyInstrumentedConnection(m, m.urlWithoutDb()) if err != nil { - return errors.Wrapf(err, "error dropping MySQL database %s", deets.Database) + return fmt.Errorf("error dropping MySQL database %s: %w", deets.Database, err) } defer db.Close() query := fmt.Sprintf("DROP DATABASE `%s`", deets.Database) @@ -149,7 +165,7 @@ func (m *mysql) DropDB() error { _, err = db.Exec(query) if err != nil { - return errors.Wrapf(err, "error dropping MySQL database %s", deets.Database) + return fmt.Errorf("error dropping MySQL database %s: %w", deets.Database, err) } log(logging.Info, "dropped database %s", deets.Database) @@ -211,7 +227,7 @@ func newMySQL(deets *ConnectionDetails) (dialect, error) { func urlParserMySQL(cd *ConnectionDetails) error { cfg, err := _mysql.ParseDSN(strings.TrimPrefix(cd.URL, "mysql://")) if err != nil { - return errors.Wrapf(err, "the URL '%s' is not supported by MySQL driver", cd.URL) + return fmt.Errorf("the URL '%s' is not supported by MySQL driver: %w", cd.URL, err) } cd.User = cfg.User diff --git a/dialect_postgresql.go b/dialect_postgresql.go index 6365232e..fe4d0236 100644 --- a/dialect_postgresql.go +++ b/dialect_postgresql.go @@ -6,18 +6,14 @@ import ( "os/exec" "sync" - // Load pgx driver - _ "github.com/jackc/pgx/v4/stdlib" - "github.com/gobuffalo/fizz" "github.com/gobuffalo/fizz/translators" + "github.com/gobuffalo/pop/v6/columns" + "github.com/gobuffalo/pop/v6/internal/defaults" + "github.com/gobuffalo/pop/v6/logging" "github.com/jackc/pgconn" + _ "github.com/jackc/pgx/v4/stdlib" // Load pgx driver "github.com/jmoiron/sqlx" - "github.com/pkg/errors" - - "github.com/gobuffalo/pop/v5/columns" - "github.com/gobuffalo/pop/v5/internal/defaults" - "github.com/gobuffalo/pop/v5/logging" ) const namePostgreSQL = "postgres" @@ -77,12 +73,15 @@ func (p *postgresql) Create(s store, model *Model, cols columns.Columns) error { err = stmt.QueryRow(model.Value).MapScan(id) if err != nil { if closeErr := stmt.Close(); closeErr != nil { - return errors.Wrapf(err, "failed to close prepared statement: %s", closeErr) + return fmt.Errorf("failed to close prepared statement: %s: %w", closeErr, err) } return err } model.setID(id[model.IDField()]) - return errors.WithMessage(stmt.Close(), "failed to close statement") + if closeErr := stmt.Close(); closeErr != nil { + return fmt.Errorf("failed to close statement: %w", closeErr) + } + return nil } return genericCreate(s, model, cols, p) } @@ -118,7 +117,7 @@ func (p *postgresql) CreateDB() error { db, err := openPotentiallyInstrumentedConnection(p, p.urlWithoutDb()) if err != nil { - return errors.Wrapf(err, "error creating PostgreSQL database %s", deets.Database) + return fmt.Errorf("error creating PostgreSQL database %s: %w", deets.Database, err) } defer db.Close() query := fmt.Sprintf("CREATE DATABASE %s", p.Quote(deets.Database)) @@ -126,7 +125,7 @@ func (p *postgresql) CreateDB() error { _, err = db.Exec(query) if err != nil { - return errors.Wrapf(err, "error creating PostgreSQL database %s", deets.Database) + return fmt.Errorf("error creating PostgreSQL database %s: %w", deets.Database, err) } log(logging.Info, "created database %s", deets.Database) @@ -138,7 +137,7 @@ func (p *postgresql) DropDB() error { db, err := openPotentiallyInstrumentedConnection(p, p.urlWithoutDb()) if err != nil { - return errors.Wrapf(err, "error dropping PostgreSQL database %s", deets.Database) + return fmt.Errorf("error dropping PostgreSQL database %s: %w", deets.Database, err) } defer db.Close() query := fmt.Sprintf("DROP DATABASE %s", p.Quote(deets.Database)) @@ -146,7 +145,7 @@ func (p *postgresql) DropDB() error { _, err = db.Exec(query) if err != nil { - return errors.Wrapf(err, "error dropping PostgreSQL database %s", deets.Database) + return fmt.Errorf("error dropping PostgreSQL database %s: %w", deets.Database, err) } log(logging.Info, "dropped database %s", deets.Database) diff --git a/dialect_sqlite.go b/dialect_sqlite.go index ce755566..49306c30 100644 --- a/dialect_sqlite.go +++ b/dialect_sqlite.go @@ -14,16 +14,13 @@ import ( "sync" "time" - "github.com/mattn/go-sqlite3" - "github.com/gobuffalo/fizz" "github.com/gobuffalo/fizz/translators" + "github.com/gobuffalo/pop/v6/columns" + "github.com/gobuffalo/pop/v6/internal/defaults" + "github.com/gobuffalo/pop/v6/logging" + "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3" // Load SQLite3 CGo driver - "github.com/pkg/errors" - - "github.com/gobuffalo/pop/v5/columns" - "github.com/gobuffalo/pop/v5/internal/defaults" - "github.com/gobuffalo/pop/v5/logging" ) const nameSQLite3 = "sqlite3" @@ -96,19 +93,28 @@ func (m *sqlite) Create(s store, model *Model, cols columns.Columns) error { } return nil } - return errors.Wrap(genericCreate(s, model, cols, m), "sqlite create") + if err := genericCreate(s, model, cols, m); err != nil { + return fmt.Errorf("sqlite create: %w", err) + } + return nil }) } func (m *sqlite) Update(s store, model *Model, cols columns.Columns) error { return m.locker(m.smGil, func() error { - return errors.Wrap(genericUpdate(s, model, cols, m), "sqlite update") + if err := genericUpdate(s, model, cols, m); err != nil { + return fmt.Errorf("sqlite update: %w", err) + } + return nil }) } func (m *sqlite) Destroy(s store, model *Model) error { return m.locker(m.smGil, func() error { - return errors.Wrap(genericDestroy(s, model, m), "sqlite destroy") + if err := genericDestroy(s, model, m); err != nil { + return fmt.Errorf("sqlite destroy: %w", err) + } + return nil }) } @@ -118,13 +124,19 @@ func (m *sqlite) Delete(s store, model *Model, query Query) error { func (m *sqlite) SelectOne(s store, model *Model, query Query) error { return m.locker(m.smGil, func() error { - return errors.Wrap(genericSelectOne(s, model, query), "sqlite select one") + if err := genericSelectOne(s, model, query); err != nil { + return fmt.Errorf("sqlite select one: %w", err) + } + return nil }) } func (m *sqlite) SelectMany(s store, models *Model, query Query) error { return m.locker(m.smGil, func() error { - return errors.Wrap(genericSelectMany(s, models, query), "sqlite select many") + if err := genericSelectMany(s, models, query); err != nil { + return fmt.Errorf("sqlite select many: %w", err) + } + return nil }) } @@ -150,16 +162,16 @@ func (m *sqlite) locker(l *sync.Mutex, fn func() error) error { func (m *sqlite) CreateDB() error { _, err := os.Stat(m.ConnectionDetails.Database) if err == nil { - return errors.Errorf("could not create SQLite database '%s'; database exists", m.ConnectionDetails.Database) + return fmt.Errorf("could not create SQLite database '%s'; database exists", m.ConnectionDetails.Database) } dir := filepath.Dir(m.ConnectionDetails.Database) err = os.MkdirAll(dir, 0766) if err != nil { - return errors.Wrapf(err, "could not create SQLite database '%s'", m.ConnectionDetails.Database) + return fmt.Errorf("could not create SQLite database '%s': %w", m.ConnectionDetails.Database, err) } _, err = os.Create(m.ConnectionDetails.Database) if err != nil { - return errors.Wrapf(err, "could not create SQLite database '%s'", m.ConnectionDetails.Database) + return fmt.Errorf("could not create SQLite database '%s': %w", m.ConnectionDetails.Database, err) } log(logging.Info, "created database '%s'", m.ConnectionDetails.Database) @@ -169,7 +181,7 @@ func (m *sqlite) CreateDB() error { func (m *sqlite) DropDB() error { err := os.Remove(m.ConnectionDetails.Database) if err != nil { - return errors.Wrapf(err, "could not drop SQLite database %s", m.ConnectionDetails.Database) + return fmt.Errorf("could not drop SQLite database %s: %w", m.ConnectionDetails.Database, err) } log(logging.Info, "dropped database '%s'", m.ConnectionDetails.Database) return nil @@ -257,7 +269,7 @@ func urlParserSQLite3(cd *ConnectionDetails) error { q, err := url.ParseQuery(dbparts[1]) if err != nil { - return errors.Wrapf(err, "unable to parse sqlite query") + return fmt.Errorf("unable to parse sqlite query: %w", err) } if cd.Options == nil { // prevent panic diff --git a/executors.go b/executors.go index 0e78a3bf..04478f66 100644 --- a/executors.go +++ b/executors.go @@ -1,15 +1,15 @@ package pop import ( + "fmt" "reflect" "time" - "github.com/gobuffalo/pop/v5/associations" - "github.com/gobuffalo/pop/v5/columns" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/associations" + "github.com/gobuffalo/pop/v6/columns" + "github.com/gobuffalo/pop/v6/logging" "github.com/gobuffalo/validate/v3" "github.com/gofrs/uuid" - "github.com/pkg/errors" ) // Reload fetch fresh data for a given model, using its ID. @@ -115,7 +115,7 @@ func (c *Connection) ValidateAndCreate(model interface{}, excludeColumns ...stri if c.eager { asos, err := associations.ForStruct(model, c.eagerFields...) if err != nil { - return verrs, errors.Wrap(err, "could not retrieve associations") + return verrs, fmt.Errorf("could not retrieve associations: %w", err) } if len(asos) == 0 { @@ -183,7 +183,7 @@ func (c *Connection) Create(model interface{}, excludeColumns ...string) error { var localIsEager = isEager asos, err := associations.ForStruct(m.Value, c.eagerFields...) if err != nil { - return errors.Wrap(err, "could not retrieve associations") + return fmt.Errorf("could not retrieve associations: %w", err) } if localIsEager && len(asos) == 0 { diff --git a/executors_test.go b/executors_test.go index 6ec3386e..3202bfad 100644 --- a/executors_test.go +++ b/executors_test.go @@ -520,6 +520,7 @@ func Test_Create_Non_PK_ID(t *testing.T) { r.NoError(tx.Create(&NonStandardID{OutfacingID: "make sure the tested entry does not have pk=0"})) count, err := tx.Count(&NonStandardID{}) + r.NoError(err) entry := &NonStandardID{ OutfacingID: "beautiful to the outside ID", } diff --git a/file_migrator.go b/file_migrator.go index 271e71a6..64169038 100644 --- a/file_migrator.go +++ b/file_migrator.go @@ -1,12 +1,12 @@ package pop import ( + "fmt" "os" "path/filepath" "strings" - "github.com/gobuffalo/pop/v5/logging" - "github.com/pkg/errors" + "github.com/gobuffalo/pop/v6/logging" ) // FileMigrator is a migrator for SQL and Fizz @@ -32,14 +32,14 @@ func NewFileMigrator(path string, c *Connection) (FileMigrator, error) { defer f.Close() content, err := MigrationContent(mf, tx, f, true) if err != nil { - return errors.Wrapf(err, "error processing %s", mf.Path) + return fmt.Errorf("error processing %s: %w", mf.Path, err) } if content == "" { return nil } err = tx.RawQuery(content).Exec() if err != nil { - return errors.Wrapf(err, "error executing %s, sql: %s", mf.Path, content) + return fmt.Errorf("error executing %s, sql: %s: %w", mf.Path, content, err) } return nil } diff --git a/finders.go b/finders.go index 440fb703..c90d1032 100644 --- a/finders.go +++ b/finders.go @@ -2,17 +2,16 @@ package pop import ( "database/sql" + "errors" "fmt" "reflect" "regexp" "strconv" "strings" + "github.com/gobuffalo/pop/v6/associations" + "github.com/gobuffalo/pop/v6/logging" "github.com/gofrs/uuid" - "github.com/pkg/errors" - - "github.com/gobuffalo/pop/v5/associations" - "github.com/gobuffalo/pop/v5/logging" ) var rLimitOffset = regexp.MustCompile("(?i)(limit [0-9]+ offset [0-9]+)$") @@ -147,7 +146,7 @@ func (q *Query) All(models interface{}) error { }) if err != nil { - return err //errors.Wrap(err, "unable to fetch records") + return fmt.Errorf("unable to fetch records: %w", err) } if q.eager { @@ -229,7 +228,7 @@ func (q *Query) eagerDefaultAssociations(model interface{}) error { // eagerAssociations for a single element assos, err := associations.ForStruct(model, q.eagerFields...) if err != nil { - return errors.Wrap(err, "could not retrieve associations") + return fmt.Errorf("could not retrieve associations: %w", err) } // disable eager mode for current connection. @@ -269,7 +268,7 @@ func (q *Query) eagerDefaultAssociations(model interface{}) error { err = query.First(association.Interface()) } - if err != nil && errors.Cause(err) != sql.ErrNoRows { + if err != nil && !errors.Is(err, sql.ErrNoRows) { return err } diff --git a/fix/anko_test.go b/fix/anko_test.go index 011a3b30..b7982b67 100644 --- a/fix/anko_test.go +++ b/fix/anko_test.go @@ -2,23 +2,37 @@ package fix import ( "io" + "io/fs" "io/ioutil" + "os" "strings" "testing" - "github.com/gobuffalo/packr/v2" "github.com/stretchr/testify/require" ) func Test_Anko(t *testing.T) { r := require.New(t) - box := packr.New("./fixtures/anko", "./fixtures/anko") - err := box.Walk(func(path string, info packr.File) error { + fsys := os.DirFS("fixtures/anko") + err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + f, err := fsys.Open(path) + if err != nil { + return err + } + if strings.HasPrefix(path, "pass") { - t.Run(path, testPass(path, info)) + t.Run(path, testPass(path, f)) return nil } - t.Run(path, testFail(path, info)) + t.Run(path, testFail(path, f)) return nil }) r.NoError(err) diff --git a/fix/auto_timestamps_off_test.go b/fix/auto_timestamps_off_test.go index 8c72f900..490215c9 100644 --- a/fix/auto_timestamps_off_test.go +++ b/fix/auto_timestamps_off_test.go @@ -1,40 +1,48 @@ package fix import ( - "io/ioutil" + "io/fs" + "os" "regexp" "testing" - "github.com/gobuffalo/packr/v2" "github.com/stretchr/testify/require" ) func Test_AutoTimestampsOff(t *testing.T) { r := require.New(t) - box := packr.New("./fixtures/auto_timestamps_off/raw", "./fixtures/auto_timestamps_off/raw") - boxPatched := packr.New("./fixtures/auto_timestamps_off/patched", "./fixtures/auto_timestamps_off/patched") + box := os.DirFS("fixtures/auto_timestamps_off/raw") + boxPatched := os.DirFS("fixtures/auto_timestamps_off/patched") + + err := fs.WalkDir(box, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } - err := box.Walk(func(path string, info packr.File) error { t.Run(path, func(tt *testing.T) { rr := require.New(tt) - b, err := ioutil.ReadAll(info) + b, err := fs.ReadFile(box, path) rr.NoError(err) body := string(b) patched, err := AutoTimestampsOff(body) rr.NoError(err) - expected, err := boxPatched.FindString(path) + expected, err := fs.ReadFile(boxPatched, path) rr.NoError(err) re := regexp.MustCompile(`(?m)([\n\r])+$`) - cleaned := re.ReplaceAllString(expected, "") + cleaned := re.ReplaceAllString(string(expected), "") cleanedPatched := re.ReplaceAllString(patched, "") rr.Equal(cleaned, cleanedPatched) - }) return nil }) + r.NoError(err) } diff --git a/genny/config/config-packr.go b/genny/config/config-packr.go deleted file mode 100644 index 5429dc52..00000000 --- a/genny/config/config-packr.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !skippackr -// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. - -// You can use the "packr clean" command to clean up this, -// and any other packr generated files. -package config - -import _ "github.com/gobuffalo/pop/v5/packrd" diff --git a/genny/config/config.go b/genny/config/config.go index 3c6b3f77..41066a67 100644 --- a/genny/config/config.go +++ b/genny/config/config.go @@ -1,15 +1,16 @@ package config import ( + "embed" "fmt" "path/filepath" "github.com/gobuffalo/genny/v2" "github.com/gobuffalo/genny/v2/gogen" - "github.com/gobuffalo/packr/v2" ) -var templates = packr.New("pop:genny:config", "../config/templates") +//go:embed templates/* +var templates embed.FS // New generator to create a database.yml file func New(opts *Options) (*genny.Generator, error) { @@ -18,7 +19,7 @@ func New(opts *Options) (*genny.Generator, error) { return g, err } - f, err := templates.Open(opts.Dialect + ".yml.tmpl") + f, err := templates.Open("templates/" + opts.Dialect + ".yml.tmpl") if err != nil { return g, fmt.Errorf("unable to find database.yml template for dialect %s", opts.Dialect) } diff --git a/genny/config/config_test.go b/genny/config/config_test.go index 0a28ca00..b783b8bd 100644 --- a/genny/config/config_test.go +++ b/genny/config/config_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/gobuffalo/genny/v2" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/stretchr/testify/require" ) diff --git a/genny/config/options.go b/genny/config/options.go index 686acc91..b98e13f1 100644 --- a/genny/config/options.go +++ b/genny/config/options.go @@ -1,9 +1,8 @@ package config import ( - "os" - "errors" + "os" ) // Options needed for the config generator diff --git a/genny/fizz/cempty/options.go b/genny/fizz/cempty/options.go index 9843ec89..585d1ea5 100644 --- a/genny/fizz/cempty/options.go +++ b/genny/fizz/cempty/options.go @@ -1,11 +1,11 @@ package cempty import ( + "errors" "fmt" "time" "github.com/gobuffalo/flect/name" - "github.com/pkg/errors" ) var nowFunc = time.Now @@ -44,7 +44,7 @@ func (opts *Options) Validate() error { opts.Type = "fizz" } if opts.Type != "fizz" && opts.Type != "sql" { - return errors.Errorf("%s migration type is not allowed", opts.Type) + return fmt.Errorf("%s migration type is not allowed", opts.Type) } if opts.Type == "sql" && opts.Translator == nil { return errors.New("sql migrations require a fizz translator") diff --git a/genny/fizz/ctable/create_table.go b/genny/fizz/ctable/create_table.go index 019b3151..630552dc 100644 --- a/genny/fizz/ctable/create_table.go +++ b/genny/fizz/ctable/create_table.go @@ -1,13 +1,13 @@ package ctable import ( + "errors" "fmt" "path/filepath" "strings" "github.com/gobuffalo/fizz" "github.com/gobuffalo/genny/v2" - "github.com/pkg/errors" ) // New creates a generator to make files for a table based diff --git a/genny/fizz/ctable/options.go b/genny/fizz/ctable/options.go index 08c2dad3..9904a633 100644 --- a/genny/fizz/ctable/options.go +++ b/genny/fizz/ctable/options.go @@ -1,14 +1,13 @@ package ctable import ( + "errors" "fmt" "time" - "github.com/gobuffalo/fizz" - "github.com/gobuffalo/attrs" + "github.com/gobuffalo/fizz" "github.com/gobuffalo/flect/name" - "github.com/pkg/errors" ) var nowFunc = time.Now @@ -51,7 +50,7 @@ func (opts *Options) Validate() error { opts.Type = "fizz" } if opts.Type != "fizz" && opts.Type != "sql" { - return errors.Errorf("%s migration type is not allowed", opts.Type) + return fmt.Errorf("%s migration type is not allowed", opts.Type) } if opts.Type == "sql" && opts.Translator == nil { return errors.New("sql migrations require a fizz translator") diff --git a/genny/model/_fixtures/models/widget.go b/genny/model/_fixtures/models/widget.go index c3797912..6291bda4 100644 --- a/genny/model/_fixtures/models/widget.go +++ b/genny/model/_fixtures/models/widget.go @@ -5,7 +5,7 @@ import ( "time" "github.com/gobuffalo/nulls" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/gobuffalo/validate/v3" "github.com/gobuffalo/validate/v3/validators" "github.com/gofrs/uuid" diff --git a/genny/model/_fixtures/models/widget_empty.go b/genny/model/_fixtures/models/widget_empty.go index ef11af9f..87294e35 100644 --- a/genny/model/_fixtures/models/widget_empty.go +++ b/genny/model/_fixtures/models/widget_empty.go @@ -3,7 +3,7 @@ package models import ( "encoding/json" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/gobuffalo/validate/v3" ) diff --git a/genny/model/_fixtures/models/widget_jsonapi.go b/genny/model/_fixtures/models/widget_jsonapi.go index 1d4828d1..215eb6f2 100644 --- a/genny/model/_fixtures/models/widget_jsonapi.go +++ b/genny/model/_fixtures/models/widget_jsonapi.go @@ -5,7 +5,7 @@ import ( "time" "github.com/gobuffalo/nulls" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/gobuffalo/validate/v3" "github.com/gobuffalo/validate/v3/validators" "github.com/gofrs/uuid" diff --git a/genny/model/_fixtures/models/widget_xml.go b/genny/model/_fixtures/models/widget_xml.go index 2593259a..ebd968ff 100644 --- a/genny/model/_fixtures/models/widget_xml.go +++ b/genny/model/_fixtures/models/widget_xml.go @@ -5,7 +5,7 @@ import ( "time" "github.com/gobuffalo/nulls" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/gobuffalo/validate/v3" "github.com/gobuffalo/validate/v3/validators" "github.com/gofrs/uuid" diff --git a/genny/model/imports.go b/genny/model/imports.go index 833104f7..0812d91c 100644 --- a/genny/model/imports.go +++ b/genny/model/imports.go @@ -9,7 +9,7 @@ import ( func buildImports(opts *Options) []string { imps := map[string]bool{ "github.com/gobuffalo/validate/v3": true, - "github.com/gobuffalo/pop/v5": true, + "github.com/gobuffalo/pop/v6": true, } if opts.Encoding == "jsonapi" { imps["github.com/google/jsonapi"] = true @@ -29,7 +29,7 @@ func buildImports(opts *Options) []string { imps["github.com/gobuffalo/nulls"] = true } if strings.HasPrefix(a.GoType(), "slices") { - imps["github.com/gobuffalo/pop/v5/slices"] = true + imps["github.com/gobuffalo/pop/v6/slices"] = true } } } diff --git a/genny/model/model-packr.go b/genny/model/model-packr.go deleted file mode 100644 index 34fd7e5e..00000000 --- a/genny/model/model-packr.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !skippackr -// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. - -// You can use the "packr clean" command to clean up this, -// and any other packr generated files. -package model - -import _ "github.com/gobuffalo/pop/v5/packrd" diff --git a/genny/model/model.go b/genny/model/model.go index 84caf084..b6e07fcd 100644 --- a/genny/model/model.go +++ b/genny/model/model.go @@ -1,15 +1,19 @@ package model import ( + "embed" + "io/fs" "strings" "github.com/gobuffalo/flect" "github.com/gobuffalo/flect/name" "github.com/gobuffalo/genny/v2" "github.com/gobuffalo/genny/v2/gogen" - "github.com/gobuffalo/packr/v2" ) +//go:embed templates/* +var templates embed.FS + // New returns a generator for creating a new model func New(opts *Options) (*genny.Generator, error) { g := genny.New() @@ -18,7 +22,12 @@ func New(opts *Options) (*genny.Generator, error) { return g, err } - if err := g.Box(packr.New("github.com/gobuffalo/pop/v5/genny/model/templates", "../model/templates")); err != nil { + sub, err := fs.Sub(templates, "templates") + if err != nil { + return g, err + } + + if err := g.FS(sub); err != nil { return g, err } @@ -46,7 +55,7 @@ func New(opts *Options) (*genny.Generator, error) { t := gogen.TemplateTransformer(ctx, help) g.Transformer(t) - g.Transformer(genny.Replace("-name-", flect.Singularize(opts.Name))) - g.Transformer(genny.Replace("-path-", opts.Path)) + g.Transformer(genny.Replace("name-", flect.Singularize(opts.Name))) + g.Transformer(genny.Replace("path-", opts.Path)) return g, nil } diff --git a/genny/model/model_test.go b/genny/model/model_test.go index e02a08e3..83328670 100644 --- a/genny/model/model_test.go +++ b/genny/model/model_test.go @@ -1,13 +1,14 @@ package model import ( + "io" + "os" "strings" "testing" "github.com/gobuffalo/attrs" "github.com/gobuffalo/genny/v2/gentest" "github.com/gobuffalo/genny/v2/gogen" - "github.com/gobuffalo/packr/v2" "github.com/stretchr/testify/require" ) @@ -28,8 +29,7 @@ func Test_New(t *testing.T) { r.NoError(err) run := gentest.NewRunner() - run.With(g) - + r.NoError(run.With(g)) r.NoError(run.Run()) res := run.Results() @@ -53,8 +53,7 @@ func Test_New_Standard(t *testing.T) { r.NoError(err) run := gentest.NewRunner() - run.With(g) - + r.NoError(run.With(g)) r.NoError(run.Run()) res := run.Results() @@ -62,23 +61,30 @@ func Test_New_Standard(t *testing.T) { r.Len(res.Commands, 0) r.NoError(gentest.CompareFiles([]string{"models/widget.go", "models/widget_test.go"}, res.Files)) - box := packr.New("Test_New_Standard", "../model/_fixtures") - f, err := res.Find("models/widget_test.go") r.NoError(err) - bf, err := box.FindString(f.Name()) + + fsys := os.DirFS("_fixtures") + bf, err := fsys.Open(f.Name()) r.NoError(err) - r.Equal(bf, f.String()) + + expected, err := io.ReadAll(bf) + r.NoError(err) + r.Equal(string(expected), f.String()) f, err = res.Find("models/widget.go") + r.NoError(err) tf := gogen.FmtTransformer() f, err = tf.Transform(f) r.NoError(err) - bf, err = box.FindString(f.Name()) + bf, err = fsys.Open(f.Name()) r.NoError(err) - r.Equal(clean(bf), clean(f.String())) + + expected, err = io.ReadAll(bf) + r.NoError(err) + r.Equal(clean(string(expected)), clean(f.String())) } func Test_New_No_Attrs(t *testing.T) { @@ -90,8 +96,7 @@ func Test_New_No_Attrs(t *testing.T) { r.NoError(err) run := gentest.NewRunner() - run.With(g) - + r.NoError(run.With(g)) r.NoError(run.Run()) res := run.Results() @@ -102,10 +107,13 @@ func Test_New_No_Attrs(t *testing.T) { f, err = tf.Transform(f) r.NoError(err) - box := packr.New("Test_New_No_Attrs", "../model/_fixtures") - bf, err := box.FindString("models/widget_empty.go") + fsys := os.DirFS("_fixtures") + bf, err := fsys.Open("models/widget_empty.go") r.NoError(err) - r.Equal(clean(bf), clean(f.String())) + + s, err := io.ReadAll(bf) + r.NoError(err) + r.Equal(clean(string(s)), clean(f.String())) } func Test_New_XML(t *testing.T) { @@ -122,8 +130,7 @@ func Test_New_XML(t *testing.T) { r.NoError(err) run := gentest.NewRunner() - run.With(g) - + r.NoError(run.With(g)) r.NoError(run.Run()) res := run.Results() @@ -131,23 +138,30 @@ func Test_New_XML(t *testing.T) { r.Len(res.Commands, 0) r.NoError(gentest.CompareFiles([]string{"models/widget.go", "models/widget_test.go"}, res.Files)) - box := packr.New("Test_New_XML", "../model/_fixtures") - f, err := res.Find("models/widget_test.go") r.NoError(err) - bf, err := box.FindString(f.Name()) + + fsys := os.DirFS("_fixtures") + bf, err := fsys.Open(f.Name()) + r.NoError(err) + + s, err := io.ReadAll(bf) r.NoError(err) - r.Equal(bf, f.String()) + r.Equal(string(s), f.String()) f, err = res.Find("models/widget.go") + r.NoError(err) tf := gogen.FmtTransformer() f, err = tf.Transform(f) r.NoError(err) - bf, err = box.FindString("models/widget_xml.go") + bf, err = fsys.Open("models/widget_xml.go") r.NoError(err) - r.Equal(clean(bf), clean(f.String())) + + s, err = io.ReadAll(bf) + r.NoError(err) + r.Equal(clean(string(s)), clean(f.String())) } func Test_New_JSONAPI(t *testing.T) { @@ -164,8 +178,7 @@ func Test_New_JSONAPI(t *testing.T) { r.NoError(err) run := gentest.NewRunner() - run.With(g) - + r.NoError(run.With(g)) r.NoError(run.Run()) res := run.Results() @@ -173,23 +186,28 @@ func Test_New_JSONAPI(t *testing.T) { r.Len(res.Commands, 0) r.NoError(gentest.CompareFiles([]string{"models/widget.go", "models/widget_test.go"}, res.Files)) - box := packr.New("Test_New_JSONAPI", "../model/_fixtures") - f, err := res.Find("models/widget_test.go") r.NoError(err) - bf, err := box.FindString(f.Name()) + + fsys := os.DirFS("_fixtures") + bf, err := fsys.Open(f.Name()) + r.NoError(err) + s, err := io.ReadAll(bf) r.NoError(err) - r.Equal(bf, f.String()) + r.Equal(string(s), f.String()) f, err = res.Find("models/widget.go") + r.NoError(err) tf := gogen.FmtTransformer() f, err = tf.Transform(f) r.NoError(err) - bf, err = box.FindString("models/widget_jsonapi.go") + bf, err = fsys.Open("models/widget_jsonapi.go") + r.NoError(err) + s, err = io.ReadAll(bf) r.NoError(err) - r.Equal(clean(bf), clean(f.String())) + r.Equal(clean(string(s)), clean(f.String())) } func Test_New_Package(t *testing.T) { @@ -202,8 +220,7 @@ func Test_New_Package(t *testing.T) { r.NoError(err) run := gentest.NewRunner() - run.With(g) - + r.NoError(run.With(g)) r.NoError(run.Run()) res := run.Results() diff --git a/genny/model/options.go b/genny/model/options.go index 2249ce98..99f2cd1e 100644 --- a/genny/model/options.go +++ b/genny/model/options.go @@ -1,11 +1,12 @@ package model import ( + "errors" + "fmt" "path/filepath" "strings" "github.com/gobuffalo/attrs" - "github.com/pkg/errors" ) // Options for generating a new model @@ -39,7 +40,7 @@ func (opts *Options) Validate() error { } opts.Encoding = strings.ToLower(opts.Encoding) if opts.Encoding != "json" && opts.Encoding != "jsonapi" && opts.Encoding != "xml" { - return errors.Errorf("unsupported encoding option %s", opts.Encoding) + return fmt.Errorf("unsupported encoding option %s", opts.Encoding) } return opts.forceDefaults() diff --git a/genny/model/templates/-path-/-name-.go.tmpl b/genny/model/templates/path-/name-.go.tmpl similarity index 100% rename from genny/model/templates/-path-/-name-.go.tmpl rename to genny/model/templates/path-/name-.go.tmpl diff --git a/genny/model/templates/-path-/-name-_test.go.tmpl b/genny/model/templates/path-/name-_test.go.tmpl similarity index 100% rename from genny/model/templates/-path-/-name-_test.go.tmpl rename to genny/model/templates/path-/name-_test.go.tmpl diff --git a/go.mod b/go.mod index 2438e454..bc0f58e3 100644 --- a/go.mod +++ b/go.mod @@ -1,35 +1,28 @@ -module github.com/gobuffalo/pop/v5 +module github.com/gobuffalo/pop/v6 -go 1.15 - -replace github.com/mattn/go-sqlite3 => github.com/mattn/go-sqlite3 v1.14.7 +go 1.16 require ( - github.com/fatih/color v1.9.0 - github.com/go-sql-driver/mysql v1.5.0 - github.com/gobuffalo/attrs v0.1.0 - github.com/gobuffalo/envy v1.8.1 + github.com/fatih/color v1.13.0 + github.com/go-sql-driver/mysql v1.6.0 + github.com/gobuffalo/attrs v1.0.1 + github.com/gobuffalo/envy v1.10.1 github.com/gobuffalo/fizz v1.10.0 - github.com/gobuffalo/flect v0.2.1 - github.com/gobuffalo/genny/v2 v2.0.5 - github.com/gobuffalo/helpers v0.6.1 // indirect - github.com/gobuffalo/logger v1.0.3 - github.com/gobuffalo/nulls v0.2.0 - github.com/gobuffalo/packd v1.0.0 - github.com/gobuffalo/packr/v2 v2.8.0 - github.com/gobuffalo/plush/v4 v4.0.0 - github.com/gobuffalo/validate/v3 v3.1.0 - github.com/gofrs/uuid v3.2.0+incompatible - github.com/jackc/pgconn v1.8.1 - github.com/jackc/pgx/v4 v4.11.0 - github.com/jmoiron/sqlx v1.3.3 - github.com/karrick/godirwalk v1.16.1 // indirect - github.com/lib/pq v1.10.1 + github.com/gobuffalo/flect v0.2.4 + github.com/gobuffalo/genny/v2 v2.0.8 + github.com/gobuffalo/logger v1.0.6 + github.com/gobuffalo/nulls v0.4.1 + github.com/gobuffalo/plush/v4 v4.1.9 + github.com/gobuffalo/validate/v3 v3.3.1 + github.com/gofrs/uuid v4.1.0+incompatible + github.com/jackc/pgconn v1.10.1 + github.com/jackc/pgx/v4 v4.13.0 + github.com/jmoiron/sqlx v1.3.4 + github.com/lib/pq v1.10.4 github.com/luna-duclos/instrumentedsql v1.1.3 - github.com/mattn/go-sqlite3 v2.0.3+incompatible - github.com/pkg/errors v0.9.1 - github.com/spf13/cobra v0.0.6 - github.com/stretchr/testify v1.5.1 - golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e - gopkg.in/yaml.v2 v2.2.8 + github.com/mattn/go-sqlite3 v1.14.9 + github.com/spf13/cobra v1.2.1 + github.com/stretchr/testify v1.7.0 + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c + gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index ce7ca05f..83673c4e 100644 --- a/go.sum +++ b/go.sum @@ -1,157 +1,202 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/attrs v0.1.0 h1:LY6/rbhPD/hfa+AfviaMXBmZBGb0fGHF12yg7f3dPQA= -github.com/gobuffalo/attrs v0.1.0/go.mod h1:fmNpaWyHM0tRm8gCZWKx8yY9fvaNLo2PyzBNSrBZ5Hw= -github.com/gobuffalo/envy v1.8.1 h1:RUr68liRvs0TS1D5qdW3mQv2SjAsu1QWMCx1tG4kDjs= -github.com/gobuffalo/envy v1.8.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= +github.com/gobuffalo/attrs v1.0.1 h1:Z84c0uuGKg58mhcLQODAqE/Sbxg8GgwjvV9nekZPs5c= +github.com/gobuffalo/attrs v1.0.1/go.mod h1:qGdnq2RukKtBl4ASJit0OFckc5XGSyTFk98SvRpMFrQ= +github.com/gobuffalo/envy v1.10.1 h1:ppDLoXv2feQ5nus4IcgtyMdHQkKng2lhJCIm33cblM0= +github.com/gobuffalo/envy v1.10.1/go.mod h1:AWx4++KnNOW3JOeEvhSaq+mvgAvnMYOY1XSIin4Mago= github.com/gobuffalo/fizz v1.10.0 h1:I8vad0PnmR+CLjSnZ5L5jlhBm4S88UIGOoZZL3/3e24= github.com/gobuffalo/fizz v1.10.0/go.mod h1:J2XGPO0AfJ1zKw7+2BA+6FEGAkyEsdCOLvN93WCT2WI= -github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= -github.com/gobuffalo/flect v0.2.1 h1:GPoRjEN0QObosV4XwuoWvSd5uSiL0N3e91/xqyY4crQ= -github.com/gobuffalo/flect v0.2.1/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= -github.com/gobuffalo/genny/v2 v2.0.5 h1:IH0EHcvwKT0MdASzptvkz/ViYBQELTklq1/l8Ot3Q5E= -github.com/gobuffalo/genny/v2 v2.0.5/go.mod h1:kRkJuAw9mdI37AiEYjV4Dl+TgkBDYf8HZVjLkqe5eBg= -github.com/gobuffalo/github_flavored_markdown v1.1.0 h1:8Zzj4fTRl/OP2R7sGerzSf6g2nEJnaBEJe7UAOiEvbQ= +github.com/gobuffalo/flect v0.2.4 h1:BSYA8+T60cdyq+vynaSUjqSVI9mDEg9ZfQUXKmfjo4I= +github.com/gobuffalo/flect v0.2.4/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= +github.com/gobuffalo/genny/v2 v2.0.8 h1:ZMQGusokXiFFOOMOKujcR3SqwxD3ZSlLwc81PMV0ww0= +github.com/gobuffalo/genny/v2 v2.0.8/go.mod h1:R45scCyQfff2HysNJHNanjrpvPw4Qu+rM1MOMDBB5oU= github.com/gobuffalo/github_flavored_markdown v1.1.0/go.mod h1:TSpTKWcRTI0+v7W3x8dkSKMLJSUpuVitlptCkpeY8ic= +github.com/gobuffalo/github_flavored_markdown v1.1.1 h1:kUf8ginyBOTRXcKSTPsPAqlA25vQ80+xAspLIYaxmTU= +github.com/gobuffalo/github_flavored_markdown v1.1.1/go.mod h1:yU32Pen+eorS58oxh/bNZx76zUOCJwmvyV5FBrvzOKQ= github.com/gobuffalo/helpers v0.6.0/go.mod h1:pncVrer7x/KRvnL5aJABLAuT/RhKRR9klL6dkUOhyv8= -github.com/gobuffalo/helpers v0.6.1 h1:LLcL4BsiyDQYtMRUUpyFdBFvFXQ6hNYOpwrcYeilVWM= -github.com/gobuffalo/helpers v0.6.1/go.mod h1:wInbDi0vTJKZBviURTLRMFLE4+nF2uRuuL2fnlYo7w4= -github.com/gobuffalo/logger v1.0.3 h1:YaXOTHNPCvkqqA7w05A4v0k2tCdpr+sgFlgINbQ6gqc= -github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM= -github.com/gobuffalo/nulls v0.2.0 h1:7R0Uec6JlZI02TR29zrs3KFIuUV8Sqe/s/j3yLvs+gc= -github.com/gobuffalo/nulls v0.2.0/go.mod h1:w4q8RoSCEt87Q0K0sRIZWYeIxkxog5mh3eN3C/n+dUc= -github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= -github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM= -github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI= -github.com/gobuffalo/packr/v2 v2.8.0 h1:IULGd15bQL59ijXLxEvA5wlMxsmx/ZkQv9T282zNVIY= -github.com/gobuffalo/packr/v2 v2.8.0/go.mod h1:PDk2k3vGevNE3SwVyVRgQCCXETC9SaONCNSXT1Q8M1g= -github.com/gobuffalo/plush/v4 v4.0.0 h1:ZHdmfr2R7DQ77XzWZK2PGKJOXm9NRy21EZ6Rw7FhuNw= +github.com/gobuffalo/helpers v0.6.4 h1:N9is8xgaotJzGIge1GoLYiWRpKZPqnS9RSty72OhIn8= +github.com/gobuffalo/helpers v0.6.4/go.mod h1:m2aOKsTl3KB0RUwwpxf3tykaaitujQ3irivqrlNAcJ0= +github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= +github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= +github.com/gobuffalo/nulls v0.4.1 h1:k7QVCJfMplv9VRQQLb4N1d8tXUdGvcdMNfp4BfMnG2M= +github.com/gobuffalo/nulls v0.4.1/go.mod h1:pp8e1hWTRJZFpMl4fj/CVbSMlaxjeGKkFq4RuBZi3w8= +github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= +github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= github.com/gobuffalo/plush/v4 v4.0.0/go.mod h1:ErFS3UxKqEb8fpFJT7lYErfN/Nw6vHGiDMTjxpk5bQ0= +github.com/gobuffalo/plush/v4 v4.1.9 h1:u9rQBuYCeHC0ppKxsZljk5vb1oT8PQa5EMNTAN2337s= +github.com/gobuffalo/plush/v4 v4.1.9/go.mod h1:9OOII9uAM5pZnhWu1OkQnboXJjaWMQ7kcTl3zNcxvTM= github.com/gobuffalo/tags/v3 v3.0.2/go.mod h1:ZQeN6TCTiwAFnS0dNcbDtSgZDwNKSpqajvVtt6mlYpA= -github.com/gobuffalo/tags/v3 v3.1.0 h1:mzdCYooN2VsLRr8KIAdEZ1lh1Py7JSMsiEGCGata2AQ= -github.com/gobuffalo/tags/v3 v3.1.0/go.mod h1:ZQeN6TCTiwAFnS0dNcbDtSgZDwNKSpqajvVtt6mlYpA= +github.com/gobuffalo/tags/v3 v3.1.2 h1:68sHcwFFDstXyfbk5ovbGcQFDsupgVLs+lw1XZinHJw= +github.com/gobuffalo/tags/v3 v3.1.2/go.mod h1:o3ldUfKv50jxWAC8eZHXMm8dnKW3YvyZUMr0xqUcZTI= github.com/gobuffalo/validate/v3 v3.0.0/go.mod h1:HFpjq+AIiA2RHoQnQVTFKF/ZpUPXwyw82LgyDPxQ9r0= -github.com/gobuffalo/validate/v3 v3.1.0 h1:/QQN920PciCfBs3aywtJTvDTHmBFMKoiwkshUWa/HLQ= -github.com/gobuffalo/validate/v3 v3.1.0/go.mod h1:HFpjq+AIiA2RHoQnQVTFKF/ZpUPXwyw82LgyDPxQ9r0= -github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= +github.com/gobuffalo/validate/v3 v3.3.1 h1:5YLQL22YARUsYS5ZGsPU6TrD0Utiu53N1JJ5qi+foYk= +github.com/gobuffalo/validate/v3 v3.3.1/go.mod h1:Ehu8ieNJQuUM4peDDr/0VapzdGA7RgTc3wbe51vHfS0= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= +github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -162,7 +207,6 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -171,11 +215,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -184,15 +227,18 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.8.1 h1:ySBX7Q87vOMqKU2bbmKbUvtYhauDFclYbNDYIE1/h6s= -github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8= +github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= @@ -201,56 +247,41 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.7.0 h1:6f4kVsW01QftE38ufBYxKciO6gyioXSC0ABIRLcZrGs= -github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= +github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.11.0 h1:J86tSWd3Y7nKjwT/43xZBvpi04keQWx8gNC2YkdJhZI= -github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= +github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= -github.com/jmoiron/sqlx v1.3.3 h1:j82X0bf7oQ27XeqxicSZsTU5suPwKElg3oyxNn43iTk= -github.com/jmoiron/sqlx v1.3.3/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= +github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karrick/godirwalk v1.15.3/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= -github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= -github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -261,345 +292,508 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.1 h1:6VXZrLU0jHBYyAqrSPa+MgPfnSvTPuMgK+k0o5kVFWo= -github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= +github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/luna-duclos/instrumentedsql v1.1.3 h1:t7mvC0z1jUt5A0UQ6I/0H31ryymuQRnJcWCiqV3lSAA= github.com/luna-duclos/instrumentedsql v1.1.3/go.mod h1:9J1njvFds+zN7y85EDhN9XNQLANWwZt2ULeIC8yMNYs= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= -github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= -github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA= +github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/microcosm-cc/bluemonday v1.0.16 h1:kHmAq2t7WPWLjiGvzKa5o3HzSfahUKiOq7fAPUiMNIc= +github.com/microcosm-cc/bluemonday v1.0.16/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.5.2 h1:qLvObTrvO/XRCqmkKxUlOBc48bI3efyDuAZe25QiF0w= -github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= -github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200308013534-11ec41452d41 h1:9Di9iYgOt9ThCipBxChBVhgNipDoE5mxO84rQV7D0FE= -golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/logger.go b/logger.go index 2295d9b6..3c0c213a 100644 --- a/logger.go +++ b/logger.go @@ -6,7 +6,7 @@ import ( "os" "github.com/fatih/color" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/logging" ) type logger func(lvl logging.Level, s string, args ...interface{}) diff --git a/migration_box.go b/migration_box.go index 0385cc1d..76c8ee31 100644 --- a/migration_box.go +++ b/migration_box.go @@ -1,40 +1,41 @@ package pop import ( + "fmt" + "io" + "io/fs" "strings" - "github.com/gobuffalo/packd" - "github.com/gobuffalo/pop/v5/logging" - "github.com/pkg/errors" + "github.com/gobuffalo/pop/v6/logging" ) -// MigrationBox is a wrapper around packr.Box and Migrator. -// This will allow you to run migrations from a packed box +// MigrationBox is a wrapper around fs.FS and Migrator. +// This will allow you to run migrations from a fs.FS // inside of a compiled binary. type MigrationBox struct { Migrator - Box packd.Walkable + FS fs.FS } -// NewMigrationBox from a packr.Box and a Connection. -func NewMigrationBox(box packd.Walkable, c *Connection) (MigrationBox, error) { +// NewMigrationBox from a fs.FS and a Connection. +func NewMigrationBox(fsys fs.FS, c *Connection) (MigrationBox, error) { fm := MigrationBox{ Migrator: NewMigrator(c), - Box: box, + FS: fsys, } - runner := func(f packd.File) func(mf Migration, tx *Connection) error { + runner := func(r io.Reader) func(mf Migration, tx *Connection) error { return func(mf Migration, tx *Connection) error { - content, err := MigrationContent(mf, tx, f, true) + content, err := MigrationContent(mf, tx, r, true) if err != nil { - return errors.Wrapf(err, "error processing %s", mf.Path) + return fmt.Errorf("error processing %s: %w", mf.Path, err) } if content == "" { return nil } err = tx.RawQuery(content).Exec() if err != nil { - return errors.Wrapf(err, "error executing %s, sql: %s", mf.Path, content) + return fmt.Errorf("error executing %s, sql: %s: %w", mf.Path, content, err) } return nil } @@ -48,12 +49,21 @@ func NewMigrationBox(box packd.Walkable, c *Connection) (MigrationBox, error) { return fm, nil } -func (fm *MigrationBox) findMigrations(runner func(f packd.File) func(mf Migration, tx *Connection) error) error { - return fm.Box.Walk(func(p string, f packd.File) error { - info, err := f.FileInfo() +func (fm *MigrationBox) findMigrations(runner func(r io.Reader) func(mf Migration, tx *Connection) error) error { + return fs.WalkDir(fm.FS, ".", func(path string, d fs.DirEntry, err error) error { if err != nil { return err } + + if d.IsDir() { + return nil + } + + info, err := d.Info() + if err != nil { + return err + } + match, err := ParseMigrationFilename(info.Name()) if err != nil { if strings.HasPrefix(err.Error(), "unsupported dialect") { @@ -66,8 +76,14 @@ func (fm *MigrationBox) findMigrations(runner func(f packd.File) func(mf Migrati log(logging.Warn, "ignoring file %s because it does not match the migration file pattern", info.Name()) return nil } + + f, err := fm.FS.Open(path) + if err != nil { + return err + } + mf := Migration{ - Path: p, + Path: path, Version: match.Version, Name: match.Name, DBType: match.DBType, diff --git a/migration_box_test.go b/migration_box_test.go index 7a9ada42..bd041eef 100644 --- a/migration_box_test.go +++ b/migration_box_test.go @@ -1,10 +1,10 @@ package pop import ( + "os" "testing" - "github.com/gobuffalo/packr/v2" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/logging" "github.com/stretchr/testify/require" ) @@ -30,7 +30,7 @@ func Test_MigrationBox(t *testing.T) { t.Run("finds testdata", func(t *testing.T) { r := require.New(t) - b, err := NewMigrationBox(packr.New("./testdata/migrations/multiple", "./testdata/migrations/multiple"), PDB) + b, err := NewMigrationBox(os.DirFS("testdata/migrations/multiple"), PDB) r.NoError(err) r.Equal(4, len(b.UpMigrations.Migrations)) r.Equal("mysql", b.UpMigrations.Migrations[0].DBType) @@ -43,7 +43,7 @@ func Test_MigrationBox(t *testing.T) { logs := setNewTestLogger() r := require.New(t) - b, err := NewMigrationBox(packr.New("./testdata/migrations/cluttered", "./testdata/migrations/cluttered"), PDB) + b, err := NewMigrationBox(os.DirFS("testdata/migrations/cluttered"), PDB) r.NoError(err) r.Equal(1, len(b.UpMigrations.Migrations)) r.Equal(1, len(*logs)) @@ -56,7 +56,7 @@ func Test_MigrationBox(t *testing.T) { logs := setNewTestLogger() r := require.New(t) - b, err := NewMigrationBox(packr.New("./testdata/migrations/unsupported_dialect", "./testdata/migrations/unsupported_dialect"), PDB) + b, err := NewMigrationBox(os.DirFS("testdata/migrations/unsupported_dialect"), PDB) r.NoError(err) r.Equal(0, len(b.UpMigrations.Migrations)) r.Equal(1, len(*logs)) diff --git a/migration_content.go b/migration_content.go index 2f6496ab..e879fb77 100644 --- a/migration_content.go +++ b/migration_content.go @@ -2,12 +2,12 @@ package pop import ( "bytes" + "fmt" "io" "io/ioutil" "text/template" "github.com/gobuffalo/fizz" - "github.com/pkg/errors" ) // MigrationContent returns the content of a migration. @@ -23,7 +23,7 @@ func MigrationContent(mf Migration, c *Connection, r io.Reader, usingTemplate bo var bb bytes.Buffer err = t.Execute(&bb, c.Dialect.Details()) if err != nil { - return "", errors.Wrapf(err, "could not execute migration template %s", mf.Path) + return "", fmt.Errorf("could not execute migration template %s: %w", mf.Path, err) } content = bb.String() } else { @@ -33,7 +33,7 @@ func MigrationContent(mf Migration, c *Connection, r io.Reader, usingTemplate bo if mf.Type == "fizz" { content, err = fizz.AString(content, c.Dialect.FizzTranslator()) if err != nil { - return "", errors.Wrapf(err, "could not fizz the migration %s", mf.Path) + return "", fmt.Errorf("could not fizz the migration %s: %w", mf.Path, err) } } diff --git a/migrator.go b/migrator.go index 39e19447..c0831791 100644 --- a/migrator.go +++ b/migrator.go @@ -10,8 +10,7 @@ import ( "text/tabwriter" "time" - "github.com/gobuffalo/pop/v5/logging" - "github.com/pkg/errors" + "github.com/gobuffalo/pop/v6/logging" ) var mrx = regexp.MustCompile(`^(\d+)_([^.]+)(\.[a-z0-9]+)?\.(up|down)\.(sql|fizz)$`) @@ -59,14 +58,14 @@ func (m Migrator) UpLogOnly() error { } exists, err := c.Where("version = ?", mi.Version).Exists(mtn) if err != nil { - return errors.Wrapf(err, "problem checking for migration version %s", mi.Version) + return fmt.Errorf("problem checking for migration version %s: %w", mi.Version, err) } if exists { continue } _, err = tx.Store.Exec(fmt.Sprintf("insert into %s (version) values ('%s')", mtn, mi.Version)) if err != nil { - return errors.Wrapf(err, "problem inserting migration version %s", mi.Version) + return fmt.Errorf("problem inserting migration version %s: %w", mi.Version, err) } } return nil @@ -94,7 +93,7 @@ func (m Migrator) UpTo(step int) (applied int, err error) { for _, mi := range mfs.Migrations { exists, err := c.Where("version = ?", mi.Version).Exists(mtn) if err != nil { - return errors.Wrapf(err, "problem checking for migration version %s", mi.Version) + return fmt.Errorf("problem checking for migration version %s: %w", mi.Version, err) } if exists { continue @@ -105,7 +104,10 @@ func (m Migrator) UpTo(step int) (applied int, err error) { return err } _, err = tx.Store.Exec(fmt.Sprintf("insert into %s (version) values ('%s')", mtn, mi.Version)) - return errors.Wrapf(err, "problem inserting migration version %s", mi.Version) + if err != nil { + return fmt.Errorf("problem inserting migration version %s: %w", mi.Version, err) + } + return nil }) if err != nil { return err @@ -134,7 +136,7 @@ func (m Migrator) Down(step int) error { mtn := c.MigrationTableName() count, err := c.Count(mtn) if err != nil { - return errors.Wrap(err, "migration down: unable count existing migration") + return fmt.Errorf("migration down: unable count existing migration: %w", err) } mfs := m.DownMigrations mfs.Filter(func(mf Migration) bool { @@ -152,10 +154,10 @@ func (m Migrator) Down(step int) error { for _, mi := range mfs.Migrations { exists, err := c.Where("version = ?", mi.Version).Exists(mtn) if err != nil { - return errors.Wrapf(err, "problem checking for migration version %s", mi.Version) + return fmt.Errorf("problem checking for migration version %s: %w", mi.Version, err) } if !exists { - return errors.Errorf("migration version %s does not exist", mi.Version) + return fmt.Errorf("migration version %s does not exist", mi.Version) } err = c.Transaction(func(tx *Connection) error { err := mi.Run(tx) @@ -163,7 +165,10 @@ func (m Migrator) Down(step int) error { return err } err = tx.RawQuery(fmt.Sprintf("delete from %s where version = ?", mtn), mi.Version).Exec() - return errors.Wrapf(err, "problem deleting migration version %s", mi.Version) + if err != nil { + return fmt.Errorf("problem deleting migration version %s: %w", mi.Version, err) + } + return nil }) if err != nil { return err @@ -190,7 +195,7 @@ func CreateSchemaMigrations(c *Connection) error { mtn := c.MigrationTableName() err := c.Open() if err != nil { - return errors.Wrap(err, "could not open connection") + return fmt.Errorf("could not open connection: %w", err) } _, err = c.Store.Exec(fmt.Sprintf("select * from %s", mtn)) if err == nil { @@ -201,11 +206,11 @@ func CreateSchemaMigrations(c *Connection) error { schemaMigrations := newSchemaMigrations(mtn) smSQL, err := c.Dialect.FizzTranslator().CreateTable(schemaMigrations) if err != nil { - return errors.Wrap(err, "could not build SQL for schema migration table") + return fmt.Errorf("could not build SQL for schema migration table: %w", err) } err = tx.RawQuery(smSQL).Exec() if err != nil { - return errors.Wrap(err, smSQL) + return fmt.Errorf("could not execute %s: %w", smSQL, err) } return nil }) @@ -228,7 +233,7 @@ func (m Migrator) Status(out io.Writer) error { for _, mf := range m.UpMigrations.Migrations { exists, err := m.Connection.Where("version = ?", mf.Version).Exists(m.Connection.MigrationTableName()) if err != nil { - return errors.Wrapf(err, "problem with migration") + return fmt.Errorf("problem with migration: %w", err) } state := "Pending" if exists { @@ -271,7 +276,7 @@ func (m Migrator) exec(fn func() error) error { err := m.CreateSchemaMigrations() if err != nil { - return errors.Wrap(err, "Migrator: problem creating schema migrations") + return fmt.Errorf("Migrator: problem creating schema migrations: %w", err) } return fn() } diff --git a/model.go b/model.go index d83ee380..dddbec66 100644 --- a/model.go +++ b/model.go @@ -7,12 +7,9 @@ import ( "strings" "time" - nflect "github.com/gobuffalo/flect/name" - - "github.com/gobuffalo/pop/v5/columns" - "github.com/pkg/errors" - "github.com/gobuffalo/flect" + nflect "github.com/gobuffalo/flect/name" + "github.com/gobuffalo/pop/v6/columns" "github.com/gofrs/uuid" ) @@ -78,7 +75,7 @@ func (m *Model) IDField() string { func (m *Model) PrimaryKeyType() (string, error) { fbn, err := m.fieldByName("ID") if err != nil { - return "", errors.Errorf("model %T is missing required field ID", m.Value) + return "", fmt.Errorf("model %T is missing required field ID", m.Value) } return fbn.Type().Name(), nil } diff --git a/model_test.go b/model_test.go index 1bcc7e2d..2b24a9bc 100644 --- a/model_test.go +++ b/model_test.go @@ -6,14 +6,12 @@ import ( "testing" "time" - "github.com/gobuffalo/pop/v5/testdata/models/ac" - "github.com/gobuffalo/pop/v5/testdata/models/bc" - + "github.com/gobuffalo/pop/v6/testdata/models/a" + "github.com/gobuffalo/pop/v6/testdata/models/ac" + "github.com/gobuffalo/pop/v6/testdata/models/b" + "github.com/gobuffalo/pop/v6/testdata/models/bc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "github.com/gobuffalo/pop/v5/testdata/models/a" - "github.com/gobuffalo/pop/v5/testdata/models/b" ) func Test_Model_TableName(t *testing.T) { diff --git a/packrd/packed-packr.go b/packrd/packed-packr.go deleted file mode 100644 index 1272b72f..00000000 --- a/packrd/packed-packr.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build !skippackr -// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT. - -// You can use the "packr2 clean" command to clean up this, -// and any other packr generated files. -package packrd - -import ( - "github.com/gobuffalo/packr/v2" - "github.com/gobuffalo/packr/v2/file/resolver" -) - -var _ = func() error { - const gk = "a3cfa2fe33a85ca3941b341e0c87c233" - g := packr.New(gk, "") - hgr, err := resolver.NewHexGzip(map[string]string{ - "3abfce8456ed838a8a49ed01c478f6c3": "1f8b08000000000000ffac8e414b03311085eff91543ee9b6dab450888aed89ba0d8f5bca4cda80be94ec8cc5661c97f9708ad16f5e6edf19837df575595f2b8c7407187835805e07b17702b1622b1bc24e4d239711bc768619a0c4561f390f0b97fcfb9fbb6560023633a5946c7fc46c99f94afc46261beb830333333f37246142c2c9512e44f8b318502d3d3a473c6617f9f40b7ab75dbdd366d73d3ac57ddd3e39d067df86aebfa180fe1fa48b0cbf3b345fdc3bdc0ae98c38e3c5efa9edd26a0ce59a998c88f5be969f8cbe53f35be68bfc97c040000ffff94a186dba3010000", - "61f8f853a1eb5098e29f68f19098fa64": "1f8b08000000000000ffac94516b1b490cc7dffd29747b70249038073e8e63215cdd26d0408883ed50fae41defcaf6d0d9d146a3716a8cbf7bd1aebdb6d3bad0d0079b5ded48fa4b3f692e2f2f3b052ed15155a297b4035058e33097149272159e5da22623666a02a690acd75daa24741f1967f6eb663339f0d6a30b0aeaea28374e9fd55611abadd7fbfb5f7d8d01398584899aaf268417e2a2357504c329257fea0f3e5384dc788d040682f57387f034bc87206cfd1c66c4200b84604a849cfcccce231bb1e4d35d8cc86e1737bdbad2c4a9febd3b6b95a7aaf7fceabb8255ddff95e180635be2b570c4bfcae8c48ec4086a1f42636434851ea128d7bdb057ff4082200b236067b0a25897914576d905902c908f2507308c10ac432f6e0576ee89b1e8d6a1ee3cc8c206c84dc08bba64ed421983680c31d683710e189fa3652cd4e831d7a8501936250a72e86e95fd8cb216fdbbf0564c45cc8f68b4448d0b54f703fdd232796da771b0346ccdd4610021a02532db0261695cc40076d784ba6bdd23c2eb75b25e279b0dfae58021b9e98ffbeffba3dbc9d3f03e791bfebdfab70cc166b36bf6af6dd93eeb9ec2a9da3e0e46e3e490519db4a174cae77130549f9a617dbca178b27da3db61b205da446f299fccd01f8d3e0d8637476e0dfcbe2fea3d6807a025fcc37985e90a028ae8a65b81e80b64a0aade9596fef6bd9e3095b725958252698caf781d7e3aa096422f34c69c9c6b2e1148a2ccfe2ba7ff4ce6e8918d9be476bfdf1ffa4fe3bbc1c31f8d17646df20c8c2fb2d779b3665fa7a845e97c67aa23d3a717e22f503155c86ed5ddc6bb6b2e0dbd143c0984c8780105d52ff9c2f839c219b1063bd71b21ecf6a4dbf9160000fffff8e8761fed050000", - "657982e88b05d0a50529d69f20b7ede0": "1f8b08000000000000ffd2d5d5e54a492d4bcdc92fc84dcd2bb1e2525048c94ccc494d2eb152502a2eccc92c4935560209269624262516a75a295457ebe5179414eb05e5e797d4d6c6c3b80145a9699915b5b5f148a6e9410ce0e22a492da686d12063e0661614e5a794269764e6e751c164846130f301010000ffff301e0ded19010000", - "98521a3534027340fd5523426c740661": "1f8b08000000000000ffac94516b1b490cc7dffd29747b70249038073e8e63215cdd26d0408883ed50fae41defcaf6d0d9d146a3716a8cbf7bd1aebdb6d3bad0d0079b5ded48fa4b3f692e2f2f3b052ed15155a297b4035058e330971492d2b035c53451a3113335015348d6eb2e5512ba8f8c33fb75b3991cf8ebd105057576941ba7cf6aab88d5d6ebfdfdafbec6809c42c244cd5713c20b71d19a3a82e1b4963ff5079f29426ebcc60203c1fab943781ade4310b67e0e33629005423025424e7e66e7918d58f2e92e4664a79157e1d9a557579a3ad5bf7767adf654159f5f7d57b2eafbbf321c706c4bbc168ef857199dd8911841ed44688c8ca6d02314e5ba17f6ea1f4810646104ec0c5614eb32b2c82ebb009205f2b1e40086118275e8c5adc0ce3d3116dd3ad49d0759d800b909785197ac5d2863108d21c67a30ce01e373b48c851a3de61a152ac3a644410eddadb29f71d6a27f17e08aa988f9118d96a87181ea7ea05f5a26afed340e963a01538701848096c86c0b84a5711103d85d13eaae758f08afd7c97a9d6c36e8970386e4a63feebfef8f6e274fc3fbe46df8f7eadf32049bcdaed9bfba69fbbc7b0ea7aafb38188d93434a75da86d3299fc7c1507d6a8af5f186e3c9068e6e87c9166913bde57c32437f34fa3418de1cb935f8fbbea837a11d8196f10f2716a62b0828a2bb6e05a22f9081aa7a5b5afedbf77ac654de96550acaa531be2276f8e9805b0abdd0187372aeb946208932fbaf9cfe3399a347366e92dbfd867fe83f8def060f7f345e90b5c93330bec85ee7cd9a8d9da216a5139ea98e4c9f5e88bf40c55421bb55771befaeb936f45af0241022e3051454bfe40be3e70867c41aec5cef84b0db946ee75b000000ffffd22b0ceef3050000", - "b7fae7237f47e13313508d43e77dea99": "1f8b08000000000000ffecd1416b32311006e0fbfe8a21dfd945053f616fb215040b915d4be9496232c5c5b8b364a26d59f2df4b2c6a0f655bbc095e873c7933797bbd5e62f080969a1dd63e4b004ca52c6a9f8126bd75a4f4260e95576bc59841dba6d4784e170e5fabf71056df7802b021f6f190685b1102607d900e442ef3792127f96c3593e55280180cc7693feda70301104202d090eb740b594437fc3f1c8d4f66cfe8bacc53392d040847e4cf318af98d9ce98c9a94e5b32c1e0488cbebc866304a00a8f115d51c3f0a80d9eec86006a662b5b6781cfe63b6315263f74665f9b82aa45ce6d3e366a7a8af0bfe827f845bfcf8cdcda72f679678e4ab5a8fee5ef7cdd5dd38327b1d77baa6f48bbe577f6bd57f060000ffff849b5ab1ea050000", - "f0365201a1fff056862862ae1fe97c7a": "1f8b08000000000000ff24ca31aec2300c06e0f9e5147e9d5a061f830d5489ee28343f10112751ed4e51ee8e2ad64f5ff5ebc7bf40ad71a9a6bc406dfe59efce3df7bcd2284aa74b0948b73d1a263ad2bd3596c3f8ea053c6fa562eb7d9ca8b93f513efb98c661794725831a65202859a107284a4d106443f81f26d7dd370000ffff43012beb86000000", - "fd34d2cca184d1b4064adfc3bbcec4c6": "1f8b08000000000000ffec564b6fdc36103e4bbf6220188664a8dc436f0672488db4c8a1c102497a290a67248eb574255221a96d5582ffbda01efbd4badd439d4b4fe26b66bef9e613872d96bf6345e01c53ad356c3dcebd8f63d1b44a5b4863e7be038db222b81170ff0658a338d5ecfdb06fc0fb384a9cbb11de27c359923c2c86a1789a4fff82b5e0688592934525eca62b58a99a55a58aeee9096bb5da8ea768b5fd7e1e2b6d8edc66f16a15e08e6e3f60436cad554bda7b10063a431c8a1e5ad58255d0600bbdeaf4a2055bd79dc65afc45ecb3e4a44da934790f1c2d1668082c16350537838b4a41a938b13933fa0a3793d377b2545cc88a7db45ac80a9267a324b622f13eb67d4b97001babbbd2823be418078e876abcb5560f74010038778393399a7280edfdb8fa93fad4b761f6658a7b9f3837439c8cf619ee400a9e80f7ad160deade39a0da10788fd6ea301bf8cef7610f394a801721c8e2de9753194c8e5f970ae74eabe3fd45c8d7a5330e7d1ca43891290c486541d3d74ee8bd04517268b0878280534d9678fcd4c912d263161e36a8870c96a8c9a6186916480ac1dc95128cb6a8e1b998cc0dfba11335271d478ff006a673ec67d46683f51afb5a214f6f9f8b1c6e97606671a4c9765ac273c1666847758e76663b54a3e992bb1c1e4399cf4cbc9f212d92b5473166955e13333bafe3cb17c478b9fccb0a5f94f991bf5f7f5b2ef7aba8ea10c9fffa7a0d7d4d0d90a0226b407712684bba072b1a0afd054aac6b40485ad5cedd92ee12480fe76f25ff885bcae164f14113daf3e5cf6d1864d090dd28ce028c4f1b61a6f999bace65c55ed2d5dda5eb6a4690da3fe12e407a505252199a7f06e9dddce4d93bad95363950f8667bd55d78324ce5d899efc2c45174d634965d44b7fb570573aec456d8e12f80d46ad13ccecfa15d23c9bc7f6fd69a0c49eb7e1454f37bd837960336d8624fca21acdc43b2b89bf87c824e920778590e52d4c7523fcdfa03fd31f2961e9e5e52da288a97f5962c0a29f9568a19c35fad9b7f26e99899f1bfb88e99d1e69b313386ff4f98f93b0000ffff9dfa38c7040c0000", - }) - if err != nil { - panic(err) - } - g.DefaultResolver = hgr - - func() { - b := packr.New("github.com/gobuffalo/pop/v5/genny/model/templates", "../model/templates") - b.SetResolver("-path-/-name-.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "fd34d2cca184d1b4064adfc3bbcec4c6"}) - b.SetResolver("-path-/-name-_test.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "f0365201a1fff056862862ae1fe97c7a"}) - }() - - func() { - b := packr.New("pop:genny:config", "../config/templates") - b.SetResolver("cockroach.yml.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "b7fae7237f47e13313508d43e77dea99"}) - b.SetResolver("mariadb.yml.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "98521a3534027340fd5523426c740661"}) - b.SetResolver("mysql.yml.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "61f8f853a1eb5098e29f68f19098fa64"}) - b.SetResolver("postgres.yml.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "3abfce8456ed838a8a49ed01c478f6c3"}) - b.SetResolver("sqlite3.yml.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "657982e88b05d0a50529d69f20b7ede0"}) - }() - - return nil -}() diff --git a/paginator.go b/paginator.go index 1da4d438..cfc4b6d1 100644 --- a/paginator.go +++ b/paginator.go @@ -4,7 +4,7 @@ import ( "encoding/json" "strconv" - "github.com/gobuffalo/pop/v5/internal/defaults" + "github.com/gobuffalo/pop/v6/internal/defaults" ) // PaginatorPerPageDefault is the amount of results per page diff --git a/pop_test.go b/pop_test.go index 8aa74178..bfe7ea78 100644 --- a/pop_test.go +++ b/pop_test.go @@ -7,12 +7,11 @@ import ( "time" "github.com/gobuffalo/nulls" + "github.com/gobuffalo/pop/v6/logging" "github.com/gobuffalo/validate/v3" "github.com/gobuffalo/validate/v3/validators" "github.com/gofrs/uuid" "github.com/stretchr/testify/suite" - - "github.com/gobuffalo/pop/v5/logging" ) var PDB *Connection @@ -52,18 +51,20 @@ func init() { dialect := os.Getenv("SODA_DIALECT") - if dialect != "" { - if err := LoadConfigFile(); err != nil { - stdlog.Panic(err) - } - var err error - PDB, err = Connect(dialect) - log(logging.Info, "Run test with dialect %v", dialect) - if err != nil { - stdlog.Panic(err) - } - } else { + if dialect == "" { log(logging.Info, "Skipping integration tests") + return + } + + if err := LoadConfigFile(); err != nil { + stdlog.Panic(err) + } + + var err error + log(logging.Info, "Run test with dialect %v", dialect) + PDB, err = Connect(dialect) + if err != nil { + stdlog.Panic(err) } } diff --git a/preload_associations.go b/preload_associations.go index 1498cf8b..72a7f4c3 100644 --- a/preload_associations.go +++ b/preload_associations.go @@ -7,8 +7,8 @@ import ( "strings" "github.com/gobuffalo/flect" - "github.com/gobuffalo/pop/v5/internal/defaults" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/internal/defaults" + "github.com/gobuffalo/pop/v6/logging" "github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx/reflectx" ) diff --git a/query.go b/query.go index 3b20b5aa..6e72f25f 100644 --- a/query.go +++ b/query.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/logging" ) type operation string diff --git a/query_groups.go b/query_groups.go index 7926d6ee..3df66e67 100644 --- a/query_groups.go +++ b/query_groups.go @@ -1,6 +1,6 @@ package pop -import "github.com/gobuffalo/pop/v5/logging" +import "github.com/gobuffalo/pop/v6/logging" // GroupBy will append a GROUP BY clause to the query func (q *Query) GroupBy(field string, fields ...string) *Query { diff --git a/query_having.go b/query_having.go index 1bc350ad..9fc873c7 100644 --- a/query_having.go +++ b/query_having.go @@ -1,6 +1,6 @@ package pop -import "github.com/gobuffalo/pop/v5/logging" +import "github.com/gobuffalo/pop/v6/logging" // Having will append a HAVING clause to the query func (q *Query) Having(condition string, args ...interface{}) *Query { diff --git a/query_joins.go b/query_joins.go index fa9af8d9..c8bde170 100644 --- a/query_joins.go +++ b/query_joins.go @@ -1,7 +1,7 @@ package pop import ( - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/logging" ) // Join will append a JOIN clause to the query diff --git a/slices/README.md b/slices/README.md index 4a00c895..2fed4b4a 100644 --- a/slices/README.md +++ b/slices/README.md @@ -1,17 +1,17 @@ -# github.com/gobuffalo/pop/v5/slices +# github.com/gobuffalo/pop/v6/slices This package provides support for datatypes like `JSONB` in postgres ## Installation -``` bash -$ go get github.com/gobuffalo/pop/v5/slices +```console +go get github.com/gobuffalo/pop/v6/slices ``` ## Supported Datatypes -* `slices.Map` -* `slices.Int` -* `slices.Float` +* `slices.Map` +* `slices.Int` +* `slices.Float` * `slices.String` -* `slices.UUID` \ No newline at end of file +* `slices.UUID` diff --git a/slices_test.go b/slices_test.go index 4668e4e0..3159ea87 100644 --- a/slices_test.go +++ b/slices_test.go @@ -3,7 +3,7 @@ package pop import ( "time" - "github.com/gobuffalo/pop/v5/slices" + "github.com/gobuffalo/pop/v6/slices" ) type Cake struct { diff --git a/soda/cmd/create.go b/soda/cmd/create.go index e9447cb1..a35099fe 100644 --- a/soda/cmd/create.go +++ b/soda/cmd/create.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) diff --git a/soda/cmd/drop.go b/soda/cmd/drop.go index 252219d2..cd6fcfb0 100644 --- a/soda/cmd/drop.go +++ b/soda/cmd/drop.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) diff --git a/soda/cmd/fix.go b/soda/cmd/fix.go index 629db571..a8f530ec 100644 --- a/soda/cmd/fix.go +++ b/soda/cmd/fix.go @@ -5,7 +5,7 @@ import ( "path/filepath" "strings" - "github.com/gobuffalo/pop/v5/fix" + "github.com/gobuffalo/pop/v6/fix" "github.com/spf13/cobra" ) diff --git a/soda/cmd/generate.go b/soda/cmd/generate.go index 6f27e0e7..ef25842e 100644 --- a/soda/cmd/generate.go +++ b/soda/cmd/generate.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/gobuffalo/pop/v5/soda/cmd/generate" + "github.com/gobuffalo/pop/v6/soda/cmd/generate" "github.com/spf13/cobra" ) diff --git a/soda/cmd/generate/config_cmd.go b/soda/cmd/generate/config_cmd.go index 0e267944..739340c1 100644 --- a/soda/cmd/generate/config_cmd.go +++ b/soda/cmd/generate/config_cmd.go @@ -8,9 +8,9 @@ import ( "strings" "github.com/gobuffalo/genny/v2" - "github.com/gobuffalo/pop/v5" - "github.com/gobuffalo/pop/v5/genny/config" - "github.com/gobuffalo/pop/v5/internal/defaults" + "github.com/gobuffalo/pop/v6" + "github.com/gobuffalo/pop/v6/genny/config" + "github.com/gobuffalo/pop/v6/internal/defaults" "github.com/spf13/cobra" ) diff --git a/soda/cmd/generate/fizz_cmd.go b/soda/cmd/generate/fizz_cmd.go index ea948061..b654f4f5 100644 --- a/soda/cmd/generate/fizz_cmd.go +++ b/soda/cmd/generate/fizz_cmd.go @@ -6,8 +6,8 @@ import ( "github.com/gobuffalo/attrs" "github.com/gobuffalo/genny/v2" "github.com/gobuffalo/logger" - "github.com/gobuffalo/pop/v5/genny/fizz/cempty" - "github.com/gobuffalo/pop/v5/genny/fizz/ctable" + "github.com/gobuffalo/pop/v6/genny/fizz/cempty" + "github.com/gobuffalo/pop/v6/genny/fizz/ctable" "github.com/spf13/cobra" ) diff --git a/soda/cmd/generate/model_cmd.go b/soda/cmd/generate/model_cmd.go index acfea0f3..ec7b6bef 100644 --- a/soda/cmd/generate/model_cmd.go +++ b/soda/cmd/generate/model_cmd.go @@ -7,9 +7,9 @@ import ( "github.com/gobuffalo/fizz" "github.com/gobuffalo/genny/v2" "github.com/gobuffalo/logger" - "github.com/gobuffalo/pop/v5" - "github.com/gobuffalo/pop/v5/genny/fizz/ctable" - gmodel "github.com/gobuffalo/pop/v5/genny/model" + "github.com/gobuffalo/pop/v6" + "github.com/gobuffalo/pop/v6/genny/fizz/ctable" + gmodel "github.com/gobuffalo/pop/v6/genny/model" "github.com/spf13/cobra" ) diff --git a/soda/cmd/generate/sql_cmd.go b/soda/cmd/generate/sql_cmd.go index 6dd11ccf..d5ec9044 100644 --- a/soda/cmd/generate/sql_cmd.go +++ b/soda/cmd/generate/sql_cmd.go @@ -7,9 +7,9 @@ import ( "github.com/gobuffalo/attrs" "github.com/gobuffalo/genny/v2" "github.com/gobuffalo/logger" - "github.com/gobuffalo/pop/v5" - "github.com/gobuffalo/pop/v5/genny/fizz/cempty" - "github.com/gobuffalo/pop/v5/genny/fizz/ctable" + "github.com/gobuffalo/pop/v6" + "github.com/gobuffalo/pop/v6/genny/fizz/cempty" + "github.com/gobuffalo/pop/v6/genny/fizz/ctable" "github.com/spf13/cobra" ) diff --git a/soda/cmd/migrate.go b/soda/cmd/migrate.go index 6fcf98ea..70f35534 100644 --- a/soda/cmd/migrate.go +++ b/soda/cmd/migrate.go @@ -2,10 +2,9 @@ package cmd import ( "os" - "errors" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) diff --git a/soda/cmd/migrate_down.go b/soda/cmd/migrate_down.go index 772b70b5..bf7d1e8b 100644 --- a/soda/cmd/migrate_down.go +++ b/soda/cmd/migrate_down.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) diff --git a/soda/cmd/migrate_status.go b/soda/cmd/migrate_status.go index 98d0aae4..9f6574c1 100644 --- a/soda/cmd/migrate_status.go +++ b/soda/cmd/migrate_status.go @@ -3,7 +3,7 @@ package cmd import ( "os" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) diff --git a/soda/cmd/migrate_up.go b/soda/cmd/migrate_up.go index 998c14e8..f1824147 100644 --- a/soda/cmd/migrate_up.go +++ b/soda/cmd/migrate_up.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) diff --git a/soda/cmd/reset.go b/soda/cmd/reset.go index 703110ba..7cba0902 100644 --- a/soda/cmd/reset.go +++ b/soda/cmd/reset.go @@ -3,7 +3,7 @@ package cmd import ( "os" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) diff --git a/soda/cmd/root.go b/soda/cmd/root.go index 7102ac82..5fb9f07c 100644 --- a/soda/cmd/root.go +++ b/soda/cmd/root.go @@ -5,8 +5,8 @@ import ( "os" "path/filepath" - "github.com/gobuffalo/pop/v5" - "github.com/gobuffalo/pop/v5/internal/defaults" + "github.com/gobuffalo/pop/v6" + "github.com/gobuffalo/pop/v6/internal/defaults" "github.com/spf13/cobra" ) diff --git a/soda/cmd/schema.go b/soda/cmd/schema.go index 44e95cdc..e6b7d079 100644 --- a/soda/cmd/schema.go +++ b/soda/cmd/schema.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/gobuffalo/pop/v5/soda/cmd/schema" + "github.com/gobuffalo/pop/v6/soda/cmd/schema" "github.com/spf13/cobra" ) diff --git a/soda/cmd/schema/dump.go b/soda/cmd/schema/dump.go index c75e8ac1..b8018b4c 100644 --- a/soda/cmd/schema/dump.go +++ b/soda/cmd/schema/dump.go @@ -6,7 +6,7 @@ import ( "os" "path/filepath" - "github.com/gobuffalo/pop/v5" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) diff --git a/soda/cmd/schema/load.go b/soda/cmd/schema/load.go index 2030c938..2d9908a7 100644 --- a/soda/cmd/schema/load.go +++ b/soda/cmd/schema/load.go @@ -1,10 +1,11 @@ package schema import ( + "errors" + "fmt" "os" - "github.com/gobuffalo/pop/v5" - "github.com/pkg/errors" + "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" ) @@ -26,13 +27,13 @@ var LoadCmd = &cobra.Command{ f, err := os.Open(loadOptions.input) if err != nil { - return errors.WithMessage(err, "unable to load schema file") + return fmt.Errorf("unable to load schema file: %w", err) } defer f.Close() c, err := pop.Connect(loadOptions.env) if err != nil { - return errors.WithMessage(err, "unable to connect to database") + return fmt.Errorf("unable to connect to database: %w", err) } defer c.Close() diff --git a/soda/main.go b/soda/main.go index 3a7ed255..0b990fcf 100644 --- a/soda/main.go +++ b/soda/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/gobuffalo/pop/v5/soda/cmd" + "github.com/gobuffalo/pop/v6/soda/cmd" ) func main() { diff --git a/sql_builder.go b/sql_builder.go index b0b3c5b8..18ffaa81 100644 --- a/sql_builder.go +++ b/sql_builder.go @@ -6,8 +6,8 @@ import ( "strings" "sync" - "github.com/gobuffalo/pop/v5/columns" - "github.com/gobuffalo/pop/v5/logging" + "github.com/gobuffalo/pop/v6/columns" + "github.com/gobuffalo/pop/v6/logging" "github.com/jmoiron/sqlx" ) diff --git a/tx.go b/tx.go index 4f2c5989..c34bbdb2 100644 --- a/tx.go +++ b/tx.go @@ -3,11 +3,11 @@ package pop import ( "context" "database/sql" + "fmt" "math/rand" "time" "github.com/jmoiron/sqlx" - "github.com/pkg/errors" ) func init() { @@ -26,7 +26,10 @@ func newTX(ctx context.Context, db *dB, opts *sql.TxOptions) (*Tx, error) { } tx, err := db.BeginTxx(ctx, opts) t.Tx = tx - return t, errors.Wrap(err, "could not create new transaction") + if err != nil { + return nil, fmt.Errorf("could not create new transaction: %w", err) + } + return t, nil } // TransactionContext simply returns the current transaction, From 86d67a11205c2de8579246a617caedb4ac51fbcd Mon Sep 17 00:00:00 2001 From: Antonio Pagano <645522+paganotoni@users.noreply.github.com> Date: Tue, 23 Nov 2021 14:53:22 -0500 Subject: [PATCH 26/59] Task merging master (#669) * v5.3.4 (#644) * fix: improve model ID field customization (#604) Updates places where `"id"` was hardcoded instead of using `model.IDField()`. * Ensure uninitialized map is initialized when unmarshaling json Add tests for this scenario * exclude migration_table_name from connection string * add test for OptionsString * Add support for pointer FKs when preloading a belongs_to association (#602) * feat: support context-aware tablenames (#614) This patch adds a feature which enables pop to pass down the connection context to the model's TableName() function by implementing TableName(ctx context.Context) string. The context can be used to dynamically generate tablenames which can be important for prefixed or generic tables and other use cases. * Bump pg deps (#616) * Reset to development * bumping pgx and pgconn versions Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * Latest from master (#620) * Latest from development (#617) * fix: improve model ID field customization (#604) Updates places where `"id"` was hardcoded instead of using `model.IDField()`. * Ensure uninitialized map is initialized when unmarshaling json Add tests for this scenario * exclude migration_table_name from connection string * add test for OptionsString * Add support for pointer FKs when preloading a belongs_to association (#602) * feat: support context-aware tablenames (#614) This patch adds a feature which enables pop to pass down the connection context to the model's TableName() function by implementing TableName(ctx context.Context) string. The context can be used to dynamically generate tablenames which can be important for prefixed or generic tables and other use cases. * Bump pg deps (#616) * Reset to development * bumping pgx and pgconn versions Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * adding goreleaser syntaz (#619) Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * Resolve issues in UPDATE and DELETE when using schemas (#618) * Resolve MySQL issues and improve test migrations * Bump CockroachDB to maintained and supported versions Version 2.1 has reached EoL in 2019 Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Use `PaginatorPageKey` and `PaginatorPerPageKey` variables (#615) * update pagination_test * Pass Time structure into timestamp update functions. (#625) Closes #624 * Allow nullable JSONB and resolve MySQL regression (#639) * Allow passing args to `Order` (#630) * Added connection maximum idle time configuration (#635) This PR add the possibility to configure the connection maximum idle time (https://golang.org/pkg/database/sql/#DB.SetConnMaxIdleTime). Closes #632 BREAKING CHANGE: Requires Go 1.15 from now on. * Bump sqlite to 3.35.4 / 1.14.7 (#642) * Update pg, pgx, sqlx (#643) - `jackc/pgx` to version `v4.11.0`. - `jmoiron/sqlx` to version`v1.3.3` - `lib/pq` to version`v1.10.1` * Fix Inner has many associations when passing on multiple arguments (#633) * Fix Inner has many associations when passing on multiple arguments for inner fields * Fix broken tests * clean up extractFieldAndInnerFields function Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> * Remove many to many TX condition for EagerPreload (#645) * Remove the need to use Tx when loading many to many associations * replace TX access to create a new tx.Store.Transaction() object * Added fix/tests for has_many with pointer foreign key (#647) Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Brian Buchholz <4773480+bhb603@users.noreply.github.com> Co-authored-by: Mike Pontillo Co-authored-by: Benjamin Blattberg Co-authored-by: Jonathan Duck Co-authored-by: Arthur Knoepflin * Updating Pgx (#660) * adding goreleaser syntaz * updating pgx now really * tidying Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Brian Buchholz <4773480+bhb603@users.noreply.github.com> Co-authored-by: Mike Pontillo Co-authored-by: Benjamin Blattberg Co-authored-by: Jonathan Duck Co-authored-by: Arthur Knoepflin From b72810f33e880592888e891941b62d5b5cc8a5f4 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Fri, 3 Dec 2021 11:43:18 +0100 Subject: [PATCH 27/59] Replace removed command The command has been removed from the CLI. This patch introduces a new mechanism to reliably dump the SQL schema for CockroachDB. --- dialect_cockroach.go | 35 +++++++++++++++++++++++++++++++++-- soda/cmd/migrate.go | 2 +- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/dialect_cockroach.go b/dialect_cockroach.go index 2ea10cb3..16d4d96b 100644 --- a/dialect_cockroach.go +++ b/dialect_cockroach.go @@ -1,11 +1,13 @@ package pop import ( + "bytes" "fmt" "io" "os" "os/exec" "path/filepath" + "regexp" "strings" "sync" @@ -200,13 +202,42 @@ func (p *cockroach) FizzTranslator() fizz.Translator { } func (p *cockroach) DumpSchema(w io.Writer) error { - cmd := exec.Command("cockroach", "dump", p.Details().Database, "--dump-mode=schema") + cmd := exec.Command("cockroach", "sql", "-e", "SHOW CREATE ALL TABLES", "-d", p.Details().Database, "--format", "raw") c := p.ConnectionDetails if defaults.String(c.Options["sslmode"], "disable") == "disable" || strings.Contains(c.RawOptions, "sslmode=disable") { cmd.Args = append(cmd.Args, "--insecure") } - return genericDumpSchema(p.Details(), cmd, w) + return cockroachDumpSchema(p.Details(), cmd, w) +} + +func cockroachDumpSchema(deets *ConnectionDetails, cmd *exec.Cmd, w io.Writer) error { + log(logging.SQL, strings.Join(cmd.Args, " ")) + + var bb bytes.Buffer + + cmd.Stdout = &bb + cmd.Stderr = os.Stderr + + err := cmd.Run() + if err != nil { + return err + } + + // --format raw returns comments prefixed with # which is invalid, so we make it a valid SQL comment. + result := regexp.MustCompile("(?m)^#").ReplaceAll(bb.Bytes(), []byte("-- #")) + + if _, err := w.Write(result); err != nil { + return err + } + + x := bytes.TrimSpace(result) + if len(x) == 0 { + return fmt.Errorf("unable to dump schema for %s", deets.Database) + } + + log(logging.Info, "dumped schema for %s", deets.Database) + return nil } func (p *cockroach) LoadSchema(r io.Reader) error { diff --git a/soda/cmd/migrate.go b/soda/cmd/migrate.go index 70f35534..8fa25b70 100644 --- a/soda/cmd/migrate.go +++ b/soda/cmd/migrate.go @@ -1,8 +1,8 @@ package cmd import ( - "os" "errors" + "os" "github.com/gobuffalo/pop/v6" "github.com/spf13/cobra" From 94d331f1374054e971f4d474fadb6043005e9649 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Wed, 8 Dec 2021 10:35:00 +0100 Subject: [PATCH 28/59] Resolve `EagerPreload` panic caused for pointer references Resolves a panic where `EagerPreload` tried to set `reflect.Struct` for a `reflect.Pointer` on 1.. associations. Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- pop_test.go | 21 +++++++++++++++++++++ preload_associations.go | 9 ++++++--- preload_associations_test.go | 12 ++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/pop_test.go b/pop_test.go index bfe7ea78..26184ae1 100644 --- a/pop_test.go +++ b/pop_test.go @@ -106,6 +106,27 @@ type User struct { Houses Addresses `many_to_many:"users_addresses"` } +type UserPointerAssocs struct { + ID int `db:"id"` + UserName string `db:"user_name"` + Email string `db:"email"` + Name nulls.String `db:"name"` + Alive nulls.Bool `db:"alive"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + BirthDate nulls.Time `db:"birth_date"` + Bio nulls.String `db:"bio"` + Price nulls.Float64 `db:"price"` + FullName nulls.String `db:"full_name" select:"name as full_name"` + Books Books `has_many:"books" order_by:"title asc"` + FavoriteSong *Song `has_one:"song" fk_id:"u_id"` + Houses Addresses `many_to_many:"users_addresses"` +} + +func (UserPointerAssocs) TableName() string { + return "users" +} + // Validate gets run every time you call a "Validate*" (ValidateAndSave, ValidateAndCreate, ValidateAndUpdate) method. // This method is not required and may be deleted. func (u *User) Validate(tx *Connection) (*validate.Errors, error) { diff --git a/preload_associations.go b/preload_associations.go index 72a7f4c3..d2985667 100644 --- a/preload_associations.go +++ b/preload_associations.go @@ -335,11 +335,14 @@ func preloadHasOne(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMetaInfo asocValue := slice.Elem().Index(i) if mmi.mapper.FieldByName(mvalue, "ID").Interface() == mmi.mapper.FieldByName(asocValue, foreignField.Path).Interface() || reflect.DeepEqual(mmi.mapper.FieldByName(mvalue, "ID"), mmi.mapper.FieldByName(asocValue, foreignField.Path)) { - if modelAssociationField.Kind() == reflect.Slice || modelAssociationField.Kind() == reflect.Array { + switch { + case modelAssociationField.Kind() == reflect.Slice || modelAssociationField.Kind() == reflect.Array: modelAssociationField.Set(reflect.Append(modelAssociationField, asocValue)) - continue + case modelAssociationField.Kind() == reflect.Ptr: + modelAssociationField.Elem().Set(asocValue) + default: + modelAssociationField.Set(asocValue) } - modelAssociationField.Set(asocValue) } } }) diff --git a/preload_associations_test.go b/preload_associations_test.go index 879531c2..933ef069 100644 --- a/preload_associations_test.go +++ b/preload_associations_test.go @@ -53,6 +53,18 @@ func Test_New_Implementation_For_Nplus1(t *testing.T) { a.Len(book.Writers, 1) a.Equal("Larry", book.Writers[0].Name) a.Equal("Mark", book.User.Name.String) + + usersWithPointers := []UserPointerAssocs{} + a.NoError(tx.All(&usersWithPointers)) + + // FILL THE HAS-MANY and HAS_ONE + a.NoError(preload(tx, &usersWithPointers)) + + a.Len(usersWithPointers[0].Books, 1) + a.Len(usersWithPointers[1].Books, 1) + a.Len(usersWithPointers[2].Books, 1) + a.Equal(usersWithPointers[0].FavoriteSong.UserID, users[0].ID) + a.Len(usersWithPointers[0].Houses, 1) }) } From d4a4f550fa7b118e6e36a7b0190a6c126ae03404 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Wed, 8 Dec 2021 13:45:11 +0100 Subject: [PATCH 29/59] Resolve `EagerPreload` panic caused by NullUUID Resolves a panic where `EagerPreload` was trying to set UUID into NullUUID. Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- associations/belongs_to_association.go | 21 ++++++++++++++------- associations/belongs_to_association_test.go | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/associations/belongs_to_association.go b/associations/belongs_to_association.go index fce161d0..c64d7208 100644 --- a/associations/belongs_to_association.go +++ b/associations/belongs_to_association.go @@ -128,15 +128,22 @@ func (b *belongsToAssociation) BeforeInterface() interface{} { func (b *belongsToAssociation) BeforeSetup() error { ownerID := reflect.Indirect(reflect.ValueOf(b.ownerModel.Interface())).FieldByName("ID") - if b.ownerID.CanSet() { - if n := nulls.New(b.ownerID.Interface()); n != nil { - b.ownerID.Set(reflect.ValueOf(n.Parse(ownerID.Interface()))) - } else if b.ownerID.Kind() == reflect.Ptr { - b.ownerID.Set(ownerID.Addr()) + toSet := b.ownerID + switch b.ownerID.Type().Name() { + case "NullUUID": + b.ownerID.FieldByName("Valid").Set(reflect.ValueOf(true)) + toSet = b.ownerID.FieldByName("UUID") + } + + if toSet.CanSet() { + if n := nulls.New(toSet.Interface()); n != nil { + toSet.Set(reflect.ValueOf(n.Parse(ownerID.Interface()))) + } else if toSet.Kind() == reflect.Ptr { + toSet.Set(ownerID.Addr()) } else { - b.ownerID.Set(ownerID) + toSet.Set(ownerID) } return nil } - return fmt.Errorf("could not set '%s' to '%s'", ownerID, b.ownerID) + return fmt.Errorf("could not set '%s' to '%s'", ownerID, toSet) } diff --git a/associations/belongs_to_association_test.go b/associations/belongs_to_association_test.go index f7a09ba3..ca72c137 100644 --- a/associations/belongs_to_association_test.go +++ b/associations/belongs_to_association_test.go @@ -22,6 +22,11 @@ type barBelongsTo struct { Foo fooBelongsTo `belongs_to:"foo"` } +type barBelongsToNullable struct { + FooID uuid.NullUUID `db:"foo_id"` + Foo *fooBelongsTo `belongs_to:"foo"` +} + func Test_Belongs_To_Association(t *testing.T) { a := require.New(t) @@ -50,3 +55,17 @@ func Test_Belongs_To_Association(t *testing.T) { a.Equal(nil, before[index].BeforeInterface()) } } + +func Test_Belongs_To_Nullable_Association(t *testing.T) { + a := require.New(t) + id, _ := uuid.NewV1() + + bar := barBelongsToNullable{Foo: &fooBelongsTo{id}} + as, err := associations.ForStruct(&bar, "Foo") + a.NoError(err) + + before := as.AssociationsBeforeCreatable() + for index := range before { + a.Equal(nil, before[index].BeforeSetup()) + } +} From 321cc6a621a1ac439d9d56babf1bbd843fad0285 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:21:15 +0100 Subject: [PATCH 30/59] Support pointers in n+1 `Eager` loading Resolves an issue where n+1 eager associations would error with a double pointer in `associations.ForStruct`. Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- finders.go | 9 ++++++++- finders_test.go | 36 ++++++++++++++++++++++++++++++++++++ pop_test.go | 13 +++++++------ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/finders.go b/finders.go index c90d1032..0df9cc21 100644 --- a/finders.go +++ b/finders.go @@ -282,7 +282,14 @@ func (q *Query) eagerDefaultAssociations(model interface{}) error { v = reflect.Indirect(reflect.ValueOf(model)).FieldByName(inner.Name) innerQuery := Q(query.Connection) innerQuery.eagerFields = inner.Fields - err = innerQuery.eagerAssociations(v.Addr().Interface()) + + switch v.Kind() { + case reflect.Ptr: + err = innerQuery.eagerAssociations(v.Interface()) + case reflect.Struct: + err = innerQuery.eagerAssociations(v.Addr().Interface()) + } + if err != nil { return err } diff --git a/finders_test.go b/finders_test.go index 7e2daa02..cc5bd925 100644 --- a/finders_test.go +++ b/finders_test.go @@ -314,6 +314,42 @@ func Test_Find_Eager_Has_One(t *testing.T) { }) } +func Test_Find_Eager_Has_One_With_Inner_Associations_Pointer(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + user := UserPointerAssocs{Name: nulls.NewString("Mark")} + err := tx.Create(&user) + r.NoError(err) + + coolSong := Song{Title: "Hook - Blues Traveler", UserID: user.ID} + err = tx.Create(&coolSong) + r.NoError(err) + + u := UserPointerAssocs{} + err = tx.Eager("FavoriteSong.ComposedBy").Find(&u, user.ID) + r.NoError(err) + + r.NotEqual(u.ID, 0) + r.Equal(u.Name.String, "Mark") + r.Equal(u.FavoriteSong.ID, coolSong.ID) + + // eager should work with rawquery + uid := u.ID + u = UserPointerAssocs{} + err = tx.RawQuery("select * from users where id=?", uid).First(&u) + r.NoError(err) + r.Nil(u.FavoriteSong) + + err = tx.RawQuery("select * from users where id=?", uid).Eager("FavoriteSong").First(&u) + r.NoError(err) + r.Equal(u.FavoriteSong.ID, coolSong.ID) + }) +} + func Test_Find_Eager_Has_One_With_Inner_Associations_Struct(t *testing.T) { if PDB == nil { t.Skip("skipping integration tests") diff --git a/pop_test.go b/pop_test.go index 26184ae1..fd2eb020 100644 --- a/pop_test.go +++ b/pop_test.go @@ -118,7 +118,7 @@ type UserPointerAssocs struct { Bio nulls.String `db:"bio"` Price nulls.Float64 `db:"price"` FullName nulls.String `db:"full_name" select:"name as full_name"` - Books Books `has_many:"books" order_by:"title asc"` + Books Books `has_many:"books" order_by:"title asc" fk_id:"user_id"` FavoriteSong *Song `has_one:"song" fk_id:"u_id"` Houses Addresses `many_to_many:"users_addresses"` } @@ -214,11 +214,12 @@ type Address struct { type Addresses []Address type UsersAddress struct { - ID int `db:"id"` - UserID int `db:"user_id"` - AddressID int `db:"address_id"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ID int `db:"id"` + UserPointerAssocsID int `db:"user_id"` + UserID int `db:"user_id"` + AddressID int `db:"address_id"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` } type UsersAddressQuery struct { From cd4d78c1d2bfb52ea7416b903a74c1000e023c27 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:21:33 +0100 Subject: [PATCH 31/59] Improve error message of associations.ForStruct Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- associations/associations_for_struct.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/associations/associations_for_struct.go b/associations/associations_for_struct.go index 67c8ca76..544e8786 100644 --- a/associations/associations_for_struct.go +++ b/associations/associations_for_struct.go @@ -1,7 +1,6 @@ package associations import ( - "errors" "fmt" "reflect" "regexp" @@ -30,7 +29,7 @@ var associationBuilders = map[string]associationBuilder{} func ForStruct(s interface{}, fields ...string) (Associations, error) { t, v := getModelDefinition(s) if t.Kind() != reflect.Struct { - return nil, errors.New("could not get struct associations: not a struct") + return nil, fmt.Errorf("could not get struct associations: not a struct but %T", s) } fields = trimFields(fields) associations := Associations{} From 881716771dfa434e54a43b2bedd01b9cddee5374 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:34:01 +0100 Subject: [PATCH 32/59] Add test cases for `IsZeroOfUnderlyingType` Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- associations/association.go | 4 ++++ associations/association_test.go | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 associations/association_test.go diff --git a/associations/association.go b/associations/association.go index 436c4581..8ed165a4 100644 --- a/associations/association.go +++ b/associations/association.go @@ -160,5 +160,9 @@ func fieldIsNil(f reflect.Value) bool { // IsZeroOfUnderlyingType will check if the value of anything is the equal to the Zero value of that type. func IsZeroOfUnderlyingType(x interface{}) bool { + if x == nil { + return true + } + return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface()) } diff --git a/associations/association_test.go b/associations/association_test.go new file mode 100644 index 00000000..504c52e9 --- /dev/null +++ b/associations/association_test.go @@ -0,0 +1,37 @@ +package associations + +import ( + "database/sql" + "fmt" + "github.com/gobuffalo/nulls" + "github.com/gofrs/uuid" + "github.com/stretchr/testify/assert" + "testing" +) + +func Test_IsZeroOfUnderlyingType(t *testing.T) { + for k, tc := range []struct { + in interface{} + zero bool + }{ + {in: nil, zero: true}, + {in: 0, zero: true}, + {in: 1, zero: false}, + {in: false, zero: true}, + {in: "", zero: true}, + {in: interface{}(nil), zero: true}, + {in: uuid.NullUUID{}, zero: true}, + {in: uuid.UUID{}, zero: true}, + {in: uuid.NullUUID{Valid: true}, zero: false}, + {in: nulls.Int{}, zero: true}, + {in: nulls.String{}, zero: true}, + {in: nulls.Bool{}, zero: true}, + {in: nulls.Float64{}, zero: true}, + {in: sql.NullString{}, zero: true}, + {in: sql.NullString{Valid: true}, zero: false}, + } { + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + assert.EqualValues(t, tc.zero, IsZeroOfUnderlyingType(tc.in)) + }) + } +} From e867f2c85ac620ac980710eb2753993e1df6e517 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Thu, 9 Dec 2021 17:23:25 +0100 Subject: [PATCH 33/59] Resolve an obscure bug where empty structs got loaded for NULL foreign keys Closes https://github.com/gobuffalo/pop/issues/139 Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- executors_test.go | 2 +- pop_test.go | 17 ++++-- preload_associations.go | 38 ++++++++++--- preload_associations_test.go | 57 ++++++++++++++++++- .../20181104140606_course_codes.down.fizz | 3 +- .../20181104140606_course_codes.up.fizz | 11 +++- 6 files changed, 108 insertions(+), 20 deletions(-) diff --git a/executors_test.go b/executors_test.go index 3202bfad..db00a428 100644 --- a/executors_test.go +++ b/executors_test.go @@ -1193,7 +1193,7 @@ func Test_Eager_Creation_Without_Associations(t *testing.T) { transaction(func(tx *Connection) { r := require.New(t) code := CourseCode{ - Course: Course{}, + Course: &Course{}, } err := tx.Eager().Create(&code) diff --git a/pop_test.go b/pop_test.go index fd2eb020..c9922678 100644 --- a/pop_test.go +++ b/pop_test.go @@ -291,14 +291,21 @@ type Course struct { } type CourseCode struct { - ID uuid.UUID `json:"id" db:"id"` - CreatedAt time.Time `json:"created_at" db:"created_at"` - UpdatedAt time.Time `json:"updated_at" db:"updated_at"` - CourseID uuid.UUID `json:"course_id" db:"course_id"` - Course Course `json:"-" belongs_to:"course"` + ID uuid.UUID `json:"id" db:"id"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + CourseID uuid.NullUUID `json:"course_id" db:"course_id"` + Course *Course `json:"course" belongs_to:"course" fk_id:"CourseID"` + ClassID uuid.UUID `json:"class_id" db:"class_id"` // Course Course `belongs_to:"course"` } +type Class struct { + ID uuid.UUID `json:"id" db:"id"` + Topic string `json:"topic" db:"topic"` + CourseCodes []CourseCode `json:"course_code_id" has_many:"course_codes"` +} + type ValidatableCar struct { ID int64 `db:"id"` Name string `db:"name"` diff --git a/preload_associations.go b/preload_associations.go index d2985667..6e8fec10 100644 --- a/preload_associations.go +++ b/preload_associations.go @@ -268,13 +268,18 @@ func preloadHasMany(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMetaInf // 3) iterate over every model and fill it with the assoc. foreignField := asoc.getDBFieldTaggedWith(fk) mmi.iterate(func(mvalue reflect.Value) { - modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) for i := 0; i < slice.Elem().Len(); i++ { asocValue := slice.Elem().Index(i) valueField := reflect.Indirect(mmi.mapper.FieldByName(asocValue, foreignField.Path)) if mmi.mapper.FieldByName(mvalue, "ID").Interface() == valueField.Interface() || reflect.DeepEqual(mmi.mapper.FieldByName(mvalue, "ID"), valueField) { - + // IMPORTANT + // + // FieldByName will initialize the value. It is important that this happens AFTER + // we checked whether the field should be set. Otherwise, we'll set a zero value! + // + // This is most likely the reason for https://github.com/gobuffalo/pop/issues/139 + modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) switch { case modelAssociationField.Kind() == reflect.Slice || modelAssociationField.Kind() == reflect.Array: modelAssociationField.Set(reflect.Append(modelAssociationField, asocValue)) @@ -330,11 +335,17 @@ func preloadHasOne(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMetaInfo // 3) iterate over every model and fill it with the assoc. foreignField := asoc.getDBFieldTaggedWith(fk) mmi.iterate(func(mvalue reflect.Value) { - modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) for i := 0; i < slice.Elem().Len(); i++ { asocValue := slice.Elem().Index(i) if mmi.mapper.FieldByName(mvalue, "ID").Interface() == mmi.mapper.FieldByName(asocValue, foreignField.Path).Interface() || reflect.DeepEqual(mmi.mapper.FieldByName(mvalue, "ID"), mmi.mapper.FieldByName(asocValue, foreignField.Path)) { + // IMPORTANT + // + // FieldByName will initialize the value. It is important that this happens AFTER + // we checked whether the field should be set. Otherwise, we'll set a zero value! + // + // This is most likely the reason for https://github.com/gobuffalo/pop/issues/139 + modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) switch { case modelAssociationField.Kind() == reflect.Slice || modelAssociationField.Kind() == reflect.Array: modelAssociationField.Set(reflect.Append(modelAssociationField, asocValue)) @@ -395,13 +406,18 @@ func preloadBelongsTo(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMetaI if isFieldNilPtr(mvalue, fi) { return } - modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) for i := 0; i < slice.Elem().Len(); i++ { asocValue := slice.Elem().Index(i) fkField := reflect.Indirect(mmi.mapper.FieldByName(mvalue, fi.Path)) - if fkField.Interface() == mmi.mapper.FieldByName(asocValue, "ID").Interface() || - reflect.DeepEqual(fkField, mmi.mapper.FieldByName(asocValue, "ID")) { - + field := mmi.mapper.FieldByName(asocValue, "ID") + if fkField.Interface() == field.Interface() || reflect.DeepEqual(fkField, field) { + // IMPORTANT + // + // FieldByName will initialize the value. It is important that this happens AFTER + // we checked whether the field should be set. Otherwise, we'll set a zero value! + // + // This is most likely the reason for https://github.com/gobuffalo/pop/issues/139 + modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) switch { case modelAssociationField.Kind() == reflect.Slice || modelAssociationField.Kind() == reflect.Array: modelAssociationField.Set(reflect.Append(modelAssociationField, asocValue)) @@ -500,11 +516,17 @@ func preloadManyToMany(tx *Connection, asoc *AssociationMetaInfo, mmi *ModelMeta mmi.iterate(func(mvalue reflect.Value) { id := mmi.mapper.FieldByName(mvalue, "ID").Interface() if assocFkIds, ok := mapAssoc[fmt.Sprintf("%v", id)]; ok { - modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) for i := 0; i < slice.Elem().Len(); i++ { asocValue := slice.Elem().Index(i) for _, fkid := range assocFkIds { if fmt.Sprintf("%v", fkid) == fmt.Sprintf("%v", mmi.mapper.FieldByName(asocValue, "ID").Interface()) { + // IMPORTANT + // + // FieldByName will initialize the value. It is important that this happens AFTER + // we checked whether the field should be set. Otherwise, we'll set a zero value! + // + // This is most likely the reason for https://github.com/gobuffalo/pop/issues/139 + modelAssociationField := mmi.mapper.FieldByName(mvalue, asoc.Name) modelAssociationField.Set(reflect.Append(modelAssociationField, asocValue)) } } diff --git a/preload_associations_test.go b/preload_associations_test.go index 933ef069..ba883c71 100644 --- a/preload_associations_test.go +++ b/preload_associations_test.go @@ -1,10 +1,10 @@ package pop import ( - "testing" - "github.com/gobuffalo/nulls" + "github.com/gofrs/uuid" "github.com/stretchr/testify/require" + "testing" ) func Test_New_Implementation_For_Nplus1(t *testing.T) { @@ -82,7 +82,7 @@ func Test_New_Implementation_For_Nplus1_With_UUID(t *testing.T) { courses = append(courses, course) if i == 0 { a.NoError(tx.Create(&CourseCode{ - CourseID: course.ID, + CourseID: uuid.NullUUID{UUID: course.ID, Valid: true}, })) } } @@ -113,6 +113,57 @@ func Test_New_Implementation_For_Nplus1_With_UUID(t *testing.T) { }) } +func Test_New_Implementation_For_Nplus1_With_NullUUIDs_And_FK_ID(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + + // This test suite prevents regressions of an obscure bug in the preload code which caused + // pointer values to be set with their empty values when relations did not exist. + // + // See also: https://github.com/gobuffalo/pop/issues/139 + transaction(func(tx *Connection) { + a := require.New(t) + + var course Course + a.NoError(tx.Create(&course)) + + class := &Class{Topic: "math", + // The bug only appears when we have two elements in the slice where + // one has a relation and the other one has no such relation. + CourseCodes: []CourseCode{ + {Course: &course}, + {}, + }} + + // This code basically just sets up + a.NoError(tx.Eager().Create(class)) + + var expected Class + a.NoError(tx.EagerPreload("CourseCodes.Course").First(&expected)) + + // What would happen before the patch resolved this issue is that: + // + // Classes.CourseCodes[0].Course would be the correct value (a filled struct) + // + // "course": { + // "id": "fa51f71f-e884-4641-8005-923258b814f9", + // "created_at": "2021-12-09T23:20:10.208019+01:00", + // "updated_at": "2021-12-09T23:20:10.208019+01:00" + // }, + // + // Classes.CourseCodes[1].Course would an "empty" struct of Course even though there is no relation set up: + // + // "course": { + // "id": "00000000-0000-0000-0000-000000000000", + // "created_at": "0001-01-01T00:00:00Z", + // "updated_at": "0001-01-01T00:00:00Z" + // }, + a.NotNil(expected.CourseCodes[0].Course) + a.Nil(expected.CourseCodes[1].Course) + }) +} + func Test_New_Implementation_For_Nplus1_Single(t *testing.T) { if PDB == nil { t.Skip("skipping integration tests") diff --git a/testdata/migrations/20181104140606_course_codes.down.fizz b/testdata/migrations/20181104140606_course_codes.down.fizz index 1d48c2b8..ddd542fd 100644 --- a/testdata/migrations/20181104140606_course_codes.down.fizz +++ b/testdata/migrations/20181104140606_course_codes.down.fizz @@ -1 +1,2 @@ -drop_table("course_codes") \ No newline at end of file +drop_table('classes') +drop_table("course_codes") diff --git a/testdata/migrations/20181104140606_course_codes.up.fizz b/testdata/migrations/20181104140606_course_codes.up.fizz index f5d81165..6405653f 100644 --- a/testdata/migrations/20181104140606_course_codes.up.fizz +++ b/testdata/migrations/20181104140606_course_codes.up.fizz @@ -1,5 +1,12 @@ +create_table("classes") { + t.Column("id", "uuid", {"primary": true}) + t.Column("topic", "string") + t.DisableTimestamps() +} + create_table("course_codes") { t.Column("id", "uuid", {"primary": true}) - t.Column("course_id", "uuid", {}) + t.Column("course_id", "uuid", {"null":true}) + t.Column("class_id", "uuid") t.Timestamps() -} \ No newline at end of file +} From 7c217b987dfc794190bd2399e26fa063569cf0e4 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Fri, 10 Dec 2021 09:57:06 +0100 Subject: [PATCH 34/59] Resolve association regression in finders.go Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- finders.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/finders.go b/finders.go index 0df9cc21..ccd4bbd5 100644 --- a/finders.go +++ b/finders.go @@ -286,7 +286,7 @@ func (q *Query) eagerDefaultAssociations(model interface{}) error { switch v.Kind() { case reflect.Ptr: err = innerQuery.eagerAssociations(v.Interface()) - case reflect.Struct: + default: err = innerQuery.eagerAssociations(v.Addr().Interface()) } From 3ba6312300de31d6d97f00db15347d0736627833 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Fri, 10 Dec 2021 10:13:36 +0100 Subject: [PATCH 35/59] Use dedicated migrations for preloading regression test Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- executors_test.go | 2 +- pop_test.go | 30 ++++++++++++------- preload_associations_test.go | 23 +++++++------- .../20181104140606_course_codes.down.fizz | 3 +- .../20181104140606_course_codes.up.fizz | 11 ++----- .../20210104145901_network.down.fizz | 3 ++ .../migrations/20210104145901_network.up.fizz | 18 +++++++++++ 7 files changed, 56 insertions(+), 34 deletions(-) create mode 100644 testdata/migrations/20210104145901_network.down.fizz create mode 100644 testdata/migrations/20210104145901_network.up.fizz diff --git a/executors_test.go b/executors_test.go index db00a428..3202bfad 100644 --- a/executors_test.go +++ b/executors_test.go @@ -1193,7 +1193,7 @@ func Test_Eager_Creation_Without_Associations(t *testing.T) { transaction(func(tx *Connection) { r := require.New(t) code := CourseCode{ - Course: &Course{}, + Course: Course{}, } err := tx.Eager().Create(&code) diff --git a/pop_test.go b/pop_test.go index c9922678..bb250e9b 100644 --- a/pop_test.go +++ b/pop_test.go @@ -291,19 +291,29 @@ type Course struct { } type CourseCode struct { - ID uuid.UUID `json:"id" db:"id"` - CreatedAt time.Time `json:"created_at" db:"created_at"` - UpdatedAt time.Time `json:"updated_at" db:"updated_at"` - CourseID uuid.NullUUID `json:"course_id" db:"course_id"` - Course *Course `json:"course" belongs_to:"course" fk_id:"CourseID"` - ClassID uuid.UUID `json:"class_id" db:"class_id"` + ID uuid.UUID `json:"id" db:"id"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + CourseID uuid.UUID `json:"course_id" db:"course_id"` + Course Course `json:"-" belongs_to:"course"` // Course Course `belongs_to:"course"` } -type Class struct { - ID uuid.UUID `json:"id" db:"id"` - Topic string `json:"topic" db:"topic"` - CourseCodes []CourseCode `json:"course_code_id" has_many:"course_codes"` +type NetClient struct { + ID uuid.UUID `json:"id" db:"id"` + Hops []Hop `json:"hop_id" has_many:"course_codes"` +} + +type Hop struct { + ID uuid.UUID `json:"id" db:"id"` + NetClient *NetClient `json:"net_client" belongs_to:"net_client" fk_id:"NetClientID"` + NetClientID uuid.UUID `json:"net_client_id" db:"net_client_id"` + Server *Server `json:"course" belongs_to:"server" fk_id:"CourseID"` + ServerID uuid.UUID `json:"server_id" db:"server_id"` +} + +type Server struct { + ID uuid.UUID `json:"id" db:"id"` } type ValidatableCar struct { diff --git a/preload_associations_test.go b/preload_associations_test.go index ba883c71..7fd2313a 100644 --- a/preload_associations_test.go +++ b/preload_associations_test.go @@ -2,7 +2,6 @@ package pop import ( "github.com/gobuffalo/nulls" - "github.com/gofrs/uuid" "github.com/stretchr/testify/require" "testing" ) @@ -82,7 +81,7 @@ func Test_New_Implementation_For_Nplus1_With_UUID(t *testing.T) { courses = append(courses, course) if i == 0 { a.NoError(tx.Create(&CourseCode{ - CourseID: uuid.NullUUID{UUID: course.ID, Valid: true}, + CourseID: course.ID, })) } } @@ -125,28 +124,28 @@ func Test_New_Implementation_For_Nplus1_With_NullUUIDs_And_FK_ID(t *testing.T) { transaction(func(tx *Connection) { a := require.New(t) - var course Course - a.NoError(tx.Create(&course)) + var server Server + a.NoError(tx.Create(&server)) - class := &Class{Topic: "math", + class := &NetClient{ // The bug only appears when we have two elements in the slice where // one has a relation and the other one has no such relation. - CourseCodes: []CourseCode{ - {Course: &course}, + Hops: []Hop{ + {Server: &server}, {}, }} // This code basically just sets up a.NoError(tx.Eager().Create(class)) - var expected Class + var expected NetClient a.NoError(tx.EagerPreload("CourseCodes.Course").First(&expected)) // What would happen before the patch resolved this issue is that: // // Classes.CourseCodes[0].Course would be the correct value (a filled struct) // - // "course": { + // "server": { // "id": "fa51f71f-e884-4641-8005-923258b814f9", // "created_at": "2021-12-09T23:20:10.208019+01:00", // "updated_at": "2021-12-09T23:20:10.208019+01:00" @@ -154,13 +153,13 @@ func Test_New_Implementation_For_Nplus1_With_NullUUIDs_And_FK_ID(t *testing.T) { // // Classes.CourseCodes[1].Course would an "empty" struct of Course even though there is no relation set up: // - // "course": { + // "server": { // "id": "00000000-0000-0000-0000-000000000000", // "created_at": "0001-01-01T00:00:00Z", // "updated_at": "0001-01-01T00:00:00Z" // }, - a.NotNil(expected.CourseCodes[0].Course) - a.Nil(expected.CourseCodes[1].Course) + a.NotNil(expected.Hops[0].Server) + a.Nil(expected.Hops[1].Server) }) } diff --git a/testdata/migrations/20181104140606_course_codes.down.fizz b/testdata/migrations/20181104140606_course_codes.down.fizz index ddd542fd..1d48c2b8 100644 --- a/testdata/migrations/20181104140606_course_codes.down.fizz +++ b/testdata/migrations/20181104140606_course_codes.down.fizz @@ -1,2 +1 @@ -drop_table('classes') -drop_table("course_codes") +drop_table("course_codes") \ No newline at end of file diff --git a/testdata/migrations/20181104140606_course_codes.up.fizz b/testdata/migrations/20181104140606_course_codes.up.fizz index 6405653f..f5d81165 100644 --- a/testdata/migrations/20181104140606_course_codes.up.fizz +++ b/testdata/migrations/20181104140606_course_codes.up.fizz @@ -1,12 +1,5 @@ -create_table("classes") { - t.Column("id", "uuid", {"primary": true}) - t.Column("topic", "string") - t.DisableTimestamps() -} - create_table("course_codes") { t.Column("id", "uuid", {"primary": true}) - t.Column("course_id", "uuid", {"null":true}) - t.Column("class_id", "uuid") + t.Column("course_id", "uuid", {}) t.Timestamps() -} +} \ No newline at end of file diff --git a/testdata/migrations/20210104145901_network.down.fizz b/testdata/migrations/20210104145901_network.down.fizz new file mode 100644 index 00000000..151bae5c --- /dev/null +++ b/testdata/migrations/20210104145901_network.down.fizz @@ -0,0 +1,3 @@ +drop_table("clients") +drop_table("hops") +drop_table("servers") diff --git a/testdata/migrations/20210104145901_network.up.fizz b/testdata/migrations/20210104145901_network.up.fizz new file mode 100644 index 00000000..738b5414 --- /dev/null +++ b/testdata/migrations/20210104145901_network.up.fizz @@ -0,0 +1,18 @@ +create_table("net_clients") { + t.Column("id", "uuid", {"primary": true}) + t.Column("hop_id", "uuid", {"null":true}) + t.ForeignKey("hop_id", {"hops": ["id"]}, {}) + t.DisableTimestamps() +} + +create_table("hops") { + t.Column("id", "uuid", {"primary": true}) + t.DisableTimestamps() +} + +create_table("servers") { + t.Column("id", "uuid", {"primary": true}) + t.Column("client_id", "uuid") + t.ForeignKey("client_id", {"clients": ["id"]}, {}) + t.DisableTimestamps() +} From 134d8a6e3ee74151804a611b71986f5aa3881ba0 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Fri, 10 Dec 2021 10:16:22 +0100 Subject: [PATCH 36/59] Fix code regression Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- pop_test.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pop_test.go b/pop_test.go index bb250e9b..66410330 100644 --- a/pop_test.go +++ b/pop_test.go @@ -214,12 +214,11 @@ type Address struct { type Addresses []Address type UsersAddress struct { - ID int `db:"id"` - UserPointerAssocsID int `db:"user_id"` - UserID int `db:"user_id"` - AddressID int `db:"address_id"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ID int `db:"id"` + UserID int `db:"user_id"` + AddressID int `db:"address_id"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` } type UsersAddressQuery struct { From 08f34ff4534da719bc49f17212d01bfcf4556de6 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Fri, 10 Dec 2021 10:22:55 +0100 Subject: [PATCH 37/59] Fix test code regressions Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- pop_test.go | 12 ++++++------ preload_associations_test.go | 2 +- ...rk.down.fizz => 20210104145902_network.down.fizz} | 0 ...etwork.up.fizz => 20210104145902_network.up.fizz} | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) rename testdata/migrations/{20210104145901_network.down.fizz => 20210104145902_network.down.fizz} (100%) rename testdata/migrations/{20210104145901_network.up.fizz => 20210104145902_network.up.fizz} (59%) diff --git a/pop_test.go b/pop_test.go index 66410330..43eac628 100644 --- a/pop_test.go +++ b/pop_test.go @@ -300,15 +300,15 @@ type CourseCode struct { type NetClient struct { ID uuid.UUID `json:"id" db:"id"` - Hops []Hop `json:"hop_id" has_many:"course_codes"` + Hops []Hop `json:"hop_id" has_many:"hops"` } type Hop struct { - ID uuid.UUID `json:"id" db:"id"` - NetClient *NetClient `json:"net_client" belongs_to:"net_client" fk_id:"NetClientID"` - NetClientID uuid.UUID `json:"net_client_id" db:"net_client_id"` - Server *Server `json:"course" belongs_to:"server" fk_id:"CourseID"` - ServerID uuid.UUID `json:"server_id" db:"server_id"` + ID uuid.UUID `json:"id" db:"id"` + NetClient *NetClient `json:"net_client" belongs_to:"net_client" fk_id:"NetClientID"` + NetClientID uuid.UUID `json:"net_client_id" db:"net_client_id"` + Server *Server `json:"course" belongs_to:"server" fk_id:"ServerID"` + ServerID uuid.NullUUID `json:"server_id" db:"server_id"` } type Server struct { diff --git a/preload_associations_test.go b/preload_associations_test.go index 7fd2313a..a953b392 100644 --- a/preload_associations_test.go +++ b/preload_associations_test.go @@ -139,7 +139,7 @@ func Test_New_Implementation_For_Nplus1_With_NullUUIDs_And_FK_ID(t *testing.T) { a.NoError(tx.Eager().Create(class)) var expected NetClient - a.NoError(tx.EagerPreload("CourseCodes.Course").First(&expected)) + a.NoError(tx.EagerPreload("Hops.Server").First(&expected)) // What would happen before the patch resolved this issue is that: // diff --git a/testdata/migrations/20210104145901_network.down.fizz b/testdata/migrations/20210104145902_network.down.fizz similarity index 100% rename from testdata/migrations/20210104145901_network.down.fizz rename to testdata/migrations/20210104145902_network.down.fizz diff --git a/testdata/migrations/20210104145901_network.up.fizz b/testdata/migrations/20210104145902_network.up.fizz similarity index 59% rename from testdata/migrations/20210104145901_network.up.fizz rename to testdata/migrations/20210104145902_network.up.fizz index 738b5414..3b6afc06 100644 --- a/testdata/migrations/20210104145901_network.up.fizz +++ b/testdata/migrations/20210104145902_network.up.fizz @@ -1,18 +1,18 @@ create_table("net_clients") { t.Column("id", "uuid", {"primary": true}) - t.Column("hop_id", "uuid", {"null":true}) - t.ForeignKey("hop_id", {"hops": ["id"]}, {}) t.DisableTimestamps() } create_table("hops") { t.Column("id", "uuid", {"primary": true}) + t.Column("server_id", "uuid", {"null":true}) + t.ForeignKey("server_id", {"servers": ["id"]}, {}) + t.Column("net_client_id", "uuid") + t.ForeignKey("net_client_id", {"net_clients": ["id"]}, {}) t.DisableTimestamps() } create_table("servers") { t.Column("id", "uuid", {"primary": true}) - t.Column("client_id", "uuid") - t.ForeignKey("client_id", {"clients": ["id"]}, {}) t.DisableTimestamps() } From bf0ffb2985b560dcf2a1c1e9e0c13af1b023d76b Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Fri, 10 Dec 2021 10:28:23 +0100 Subject: [PATCH 38/59] Fix sql migration order Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> --- testdata/migrations/20210104145902_network.up.fizz | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/testdata/migrations/20210104145902_network.up.fizz b/testdata/migrations/20210104145902_network.up.fizz index 3b6afc06..dc624e6c 100644 --- a/testdata/migrations/20210104145902_network.up.fizz +++ b/testdata/migrations/20210104145902_network.up.fizz @@ -3,6 +3,11 @@ create_table("net_clients") { t.DisableTimestamps() } +create_table("servers") { + t.Column("id", "uuid", {"primary": true}) + t.DisableTimestamps() +} + create_table("hops") { t.Column("id", "uuid", {"primary": true}) t.Column("server_id", "uuid", {"null":true}) @@ -11,8 +16,3 @@ create_table("hops") { t.ForeignKey("net_client_id", {"net_clients": ["id"]}, {}) t.DisableTimestamps() } - -create_table("servers") { - t.Column("id", "uuid", {"primary": true}) - t.DisableTimestamps() -} From 20bb080357d8e4d45fdde66d437f08faa3bd7fcc Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Fri, 10 Dec 2021 13:44:21 +0100 Subject: [PATCH 39/59] Resolve order issue in test --- pop_test.go | 2 +- preload_associations_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pop_test.go b/pop_test.go index 43eac628..0166e9d0 100644 --- a/pop_test.go +++ b/pop_test.go @@ -307,7 +307,7 @@ type Hop struct { ID uuid.UUID `json:"id" db:"id"` NetClient *NetClient `json:"net_client" belongs_to:"net_client" fk_id:"NetClientID"` NetClientID uuid.UUID `json:"net_client_id" db:"net_client_id"` - Server *Server `json:"course" belongs_to:"server" fk_id:"ServerID"` + Server *Server `json:"course" belongs_to:"server" fk_id:"ServerID" oder_by:"id asc"` ServerID uuid.NullUUID `json:"server_id" db:"server_id"` } diff --git a/preload_associations_test.go b/preload_associations_test.go index a953b392..507d04e4 100644 --- a/preload_associations_test.go +++ b/preload_associations_test.go @@ -158,7 +158,7 @@ func Test_New_Implementation_For_Nplus1_With_NullUUIDs_And_FK_ID(t *testing.T) { // "created_at": "0001-01-01T00:00:00Z", // "updated_at": "0001-01-01T00:00:00Z" // }, - a.NotNil(expected.Hops[0].Server) + a.NotNil(expected.Hops[0].Server, "%+v", expected.Hops[0]) a.Nil(expected.Hops[1].Server) }) } From d148b954dda168a542e78eb4faa1798a8cd5a389 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Fri, 10 Dec 2021 13:54:52 +0100 Subject: [PATCH 40/59] Ignore order when testing for nil values in test --- preload_associations_test.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/preload_associations_test.go b/preload_associations_test.go index 507d04e4..3d70bad9 100644 --- a/preload_associations_test.go +++ b/preload_associations_test.go @@ -158,8 +158,19 @@ func Test_New_Implementation_For_Nplus1_With_NullUUIDs_And_FK_ID(t *testing.T) { // "created_at": "0001-01-01T00:00:00Z", // "updated_at": "0001-01-01T00:00:00Z" // }, - a.NotNil(expected.Hops[0].Server, "%+v", expected.Hops[0]) - a.Nil(expected.Hops[1].Server) + var foundValid, foundEmpty int + for _, hop := range expected.Hops { + if hop.ServerID.Valid { + foundValid++ + a.NotNil(hop.Server, "%+v", hop) + } else { + foundEmpty++ + a.Nil(hop.Server, "%+v", hop) + } + } + + a.Equal(1, foundValid) + a.Equal(1, foundEmpty) }) } From f7abee9945219fac7af85ad7bf0f561f7126b5ef Mon Sep 17 00:00:00 2001 From: Martin Eigenbrodt Date: Mon, 14 Feb 2022 14:27:34 +0100 Subject: [PATCH 41/59] Pass Context during exec in create. (#688) --- dialect_common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialect_common.go b/dialect_common.go index 00e9e552..d0876295 100644 --- a/dialect_common.go +++ b/dialect_common.go @@ -85,7 +85,7 @@ func genericCreate(s store, model *Model, cols columns.Columns, quoter quotable) if err != nil { return err } - _, err = stmt.Exec(model.Value) + _, err = stmt.ExecContext(model.ctx, model.Value) if err != nil { if closeErr := stmt.Close(); closeErr != nil { return fmt.Errorf("failed to close prepared statement: %s: %w", closeErr, err) From 32f6994a27cff341b798bd075a973df441a33d3a Mon Sep 17 00:00:00 2001 From: Patrik Date: Tue, 22 Feb 2022 12:55:38 +0100 Subject: [PATCH 42/59] feat: support embedded struct fields (#691) --- associations/associations_for_struct.go | 10 ++++ columns/columns_for_struct.go | 50 ++++++++++++------- executors_test.go | 27 ++++++++++ pop_test.go | 11 ++++ test.sh | 2 +- .../20220214113659_embedded_struct.down.fizz | 1 + .../20220214113659_embedded_struct.up.fizz | 7 +++ 7 files changed, 89 insertions(+), 19 deletions(-) create mode 100644 testdata/migrations/20220214113659_embedded_struct.down.fizz create mode 100644 testdata/migrations/20220214113659_embedded_struct.up.fizz diff --git a/associations/associations_for_struct.go b/associations/associations_for_struct.go index 544e8786..bdd7e180 100644 --- a/associations/associations_for_struct.go +++ b/associations/associations_for_struct.go @@ -72,6 +72,16 @@ func ForStruct(s interface{}, fields ...string) (Associations, error) { for i := 0; i < t.NumField(); i++ { f := t.Field(i) + // inline embedded field + if f.Anonymous { + innerAssociations, err := ForStruct(v.Field(i).Interface(), fields...) + if err != nil { + return nil, err + } + associations = append(associations, innerAssociations...) + continue + } + // ignores those fields not included in fields list. if len(fields) > 0 && fieldIgnoredIn(fields, f.Name) { continue diff --git a/columns/columns_for_struct.go b/columns/columns_for_struct.go index a20cd426..5e09f69f 100644 --- a/columns/columns_for_struct.go +++ b/columns/columns_for_struct.go @@ -31,33 +31,47 @@ func ForStructWithAlias(s interface{}, tableName, tableAlias, idField string) (c } } - fieldCount := st.NumField() + // recursive functions to also find and add embedded struct fields + var findColumns func(st reflect.Type) + findColumns = func(t reflect.Type) { + if t.Kind() == reflect.Ptr { + t = t.Elem() + } - for i := 0; i < fieldCount; i++ { - field := st.Field(i) + fc := t.NumField() + for i := 0; i < fc; i++ { + field := t.Field(i) - popTags := TagsFor(field) - tag := popTags.Find("db") + if field.Anonymous { + findColumns(field.Type) + continue + } - if !tag.Ignored() && !tag.Empty() { - col := tag.Value + popTags := TagsFor(field) + tag := popTags.Find("db") - // add writable or readable. - tag := popTags.Find("rw") - if !tag.Empty() { - col = col + "," + tag.Value - } + if !tag.Ignored() && !tag.Empty() { + col := tag.Value - cs := columns.Add(col) + // add writable or readable. + tag := popTags.Find("rw") + if !tag.Empty() { + col = col + "," + tag.Value + } - // add select clause. - tag = popTags.Find("select") - if !tag.Empty() { - c := cs[0] - c.SetSelectSQL(tag.Value) + cs := columns.Add(col) + + // add select clause. + tag = popTags.Find("select") + if !tag.Empty() { + c := cs[0] + c.SetSelectSQL(tag.Value) + } } } } + findColumns(st) + return columns } diff --git a/executors_test.go b/executors_test.go index 3202bfad..d428e364 100644 --- a/executors_test.go +++ b/executors_test.go @@ -533,6 +533,33 @@ func Test_Create_Non_PK_ID(t *testing.T) { }) } +func Test_Embedded_Struct(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + entry := &EmbeddingStruct{ + InnerStruct: InnerStruct{}, + AdditionalField: "I am also important!", + } + r.NoError(tx.Create(entry)) + + var actual EmbeddingStruct + r.NoError(tx.Find(&actual, entry.ID)) + r.Equal(entry.AdditionalField, actual.AdditionalField) + + entry.AdditionalField = entry.AdditionalField + " updated" + r.NoError(tx.Update(entry)) + + r.NoError(tx.Find(&actual, entry.ID)) + r.Equal(entry.AdditionalField, actual.AdditionalField) + + r.NoError(tx.Destroy(entry)) + }) +} + func Test_Eager_Create_Has_Many(t *testing.T) { if PDB == nil { t.Skip("skipping integration tests") diff --git a/pop_test.go b/pop_test.go index 0166e9d0..629ea35a 100644 --- a/pop_test.go +++ b/pop_test.go @@ -476,3 +476,14 @@ type NonStandardID struct { ID int `db:"pk"` OutfacingID string `db:"id"` } + +type InnerStruct struct { + ID int `db:"id"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` +} + +type EmbeddingStruct struct { + InnerStruct + AdditionalField string `db:"additional_field"` +} diff --git a/test.sh b/test.sh index 4ea9a5f0..d99c6744 100755 --- a/test.sh +++ b/test.sh @@ -58,7 +58,7 @@ function test { ./tsoda create -e $SODA_DIALECT -c ./database.yml -p ./testdata/migrations ./tsoda migrate -e $SODA_DIALECT -c ./database.yml -p ./testdata/migrations echo "Test..." - go test -race -tags sqlite $VERBOSE ./... -count=1 + go test -race -tags sqlite $VERBOSE -count=1 ./... } function debug_test { diff --git a/testdata/migrations/20220214113659_embedded_struct.down.fizz b/testdata/migrations/20220214113659_embedded_struct.down.fizz new file mode 100644 index 00000000..ec1651dd --- /dev/null +++ b/testdata/migrations/20220214113659_embedded_struct.down.fizz @@ -0,0 +1 @@ +drop_table("embedding_structs") diff --git a/testdata/migrations/20220214113659_embedded_struct.up.fizz b/testdata/migrations/20220214113659_embedded_struct.up.fizz new file mode 100644 index 00000000..90473246 --- /dev/null +++ b/testdata/migrations/20220214113659_embedded_struct.up.fizz @@ -0,0 +1,7 @@ +create_table("embedding_structs") { + t.Column("id", "int", { "primary": true }) + + t.Column("additional_field", "string", {}) + + t.Timestamps() +} \ No newline at end of file From 2ff8b3f43a8af2a7a7595b77d3fc312aa5164e9f Mon Sep 17 00:00:00 2001 From: Eng Zer Jun Date: Sun, 10 Apr 2022 17:35:10 +0800 Subject: [PATCH 43/59] test: use `T.TempDir` to create temporary test directory This commit replaces `ioutil.TempDir` with `t.TempDir` in tests. The directory created by `t.TempDir` is automatically removed when the test and all its subtests complete. Prior to this commit, temporary directory created using `ioutil.TempDir` needs to be removed manually by calling `os.RemoveAll`, which is omitted in some tests. The error handling boilerplate e.g. defer func() { if err := os.RemoveAll(dir); err != nil { t.Fatal(err) } } is also tedious, but `t.TempDir` handles this for us nicely. Reference: https://pkg.go.dev/testing#T.TempDir Signed-off-by: Eng Zer Jun --- dialect_sqlite.go | 3 ++- dialect_sqlite_test.go | 10 ++-------- soda/cmd/generate/config_cmd_test.go | 5 +---- soda/cmd/generate/fizz_cmd_test.go | 5 +---- soda/cmd/generate/model_cmd_test.go | 9 ++------- 5 files changed, 8 insertions(+), 24 deletions(-) diff --git a/dialect_sqlite.go b/dialect_sqlite.go index 49306c30..1ac8691f 100644 --- a/dialect_sqlite.go +++ b/dialect_sqlite.go @@ -169,10 +169,11 @@ func (m *sqlite) CreateDB() error { if err != nil { return fmt.Errorf("could not create SQLite database '%s': %w", m.ConnectionDetails.Database, err) } - _, err = os.Create(m.ConnectionDetails.Database) + f, err := os.Create(m.ConnectionDetails.Database) if err != nil { return fmt.Errorf("could not create SQLite database '%s': %w", m.ConnectionDetails.Database, err) } + _ = f.Close() log(logging.Info, "created database '%s'", m.ConnectionDetails.Database) return nil diff --git a/dialect_sqlite_test.go b/dialect_sqlite_test.go index 16796f6d..83a0294a 100644 --- a/dialect_sqlite_test.go +++ b/dialect_sqlite_test.go @@ -4,8 +4,6 @@ package pop import ( "fmt" - "io/ioutil" - "os" "path/filepath" "testing" @@ -133,10 +131,8 @@ func Test_ConnectionDetails_Finalize_SQLite_OverrideOptions_Synonym_Path(t *test func Test_ConnectionDetails_FinalizeOSPath(t *testing.T) { r := require.New(t) - d, err := ioutil.TempDir("", "") - r.NoError(err) + d := t.TempDir() p := filepath.Join(d, "testdb.sqlite") - defer os.RemoveAll(p) cd := &ConnectionDetails{ Dialect: "sqlite", Database: p, @@ -148,10 +144,8 @@ func Test_ConnectionDetails_FinalizeOSPath(t *testing.T) { func TestSqlite_CreateDB(t *testing.T) { r := require.New(t) - dir, err := ioutil.TempDir("", "") - r.NoError(err) + dir := t.TempDir() p := filepath.Join(dir, "testdb.sqlite") - defer os.RemoveAll(p) cd := &ConnectionDetails{ Dialect: "sqlite", Database: p, diff --git a/soda/cmd/generate/config_cmd_test.go b/soda/cmd/generate/config_cmd_test.go index 51f21d7c..309121fb 100644 --- a/soda/cmd/generate/config_cmd_test.go +++ b/soda/cmd/generate/config_cmd_test.go @@ -1,7 +1,6 @@ package generate import ( - "io/ioutil" "os" "testing" @@ -13,9 +12,7 @@ func Test_ConfigCmd_NoArg(t *testing.T) { c := ConfigCmd c.SetArgs([]string{}) - tdir, err := ioutil.TempDir("", "testapp") - r.NoError(err) - defer os.RemoveAll(tdir) + tdir := t.TempDir() pwd, err := os.Getwd() r.NoError(err) diff --git a/soda/cmd/generate/fizz_cmd_test.go b/soda/cmd/generate/fizz_cmd_test.go index 59d3bfb1..04b7e6a3 100644 --- a/soda/cmd/generate/fizz_cmd_test.go +++ b/soda/cmd/generate/fizz_cmd_test.go @@ -1,7 +1,6 @@ package generate import ( - "io/ioutil" "os" "testing" @@ -13,9 +12,7 @@ func Test_FizzCmd_NoArg(t *testing.T) { c := FizzCmd c.SetArgs([]string{}) - tdir, err := ioutil.TempDir("", "testapp") - r.NoError(err) - defer os.RemoveAll(tdir) + tdir := t.TempDir() pwd, err := os.Getwd() r.NoError(err) diff --git a/soda/cmd/generate/model_cmd_test.go b/soda/cmd/generate/model_cmd_test.go index a70bc2e5..5dcb3de7 100644 --- a/soda/cmd/generate/model_cmd_test.go +++ b/soda/cmd/generate/model_cmd_test.go @@ -1,7 +1,6 @@ package generate import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -14,9 +13,7 @@ func Test_ModelCmd_NoArg(t *testing.T) { c := ModelCmd c.SetArgs([]string{}) - tdir, err := ioutil.TempDir("", "testapp") - r.NoError(err) - defer os.RemoveAll(tdir) + tdir := t.TempDir() pwd, err := os.Getwd() r.NoError(err) @@ -32,9 +29,7 @@ func Test_ModelCmd_NameOnly(t *testing.T) { c := ModelCmd c.SetArgs([]string{"users"}) - tdir, err := ioutil.TempDir("", "testapp") - r.NoError(err) - defer os.RemoveAll(tdir) + tdir := t.TempDir() pwd, err := os.Getwd() r.NoError(err) From d6d7437dcb03098949b98098f8086333529e219b Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Sat, 16 Apr 2022 10:22:24 -0500 Subject: [PATCH 44/59] task: adding next version number --- soda/cmd/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soda/cmd/version.go b/soda/cmd/version.go index 37ba4f67..148d5663 100644 --- a/soda/cmd/version.go +++ b/soda/cmd/version.go @@ -2,4 +2,4 @@ package cmd // Version defines the current Pop version. // this version will also be used by soda(also buffalo-pop) -const Version = "v6.0.1" +const Version = "v6.0.2" From 1dad15a4755f5ae2ae770c9837e59b912fda9afd Mon Sep 17 00:00:00 2001 From: zepatrik Date: Wed, 20 Apr 2022 15:41:03 +0300 Subject: [PATCH 45/59] fix: associations for embedded fields --- associations/associations_for_struct.go | 27 ++++- executors_test.go | 132 ++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 4 deletions(-) diff --git a/associations/associations_for_struct.go b/associations/associations_for_struct.go index bdd7e180..529b210b 100644 --- a/associations/associations_for_struct.go +++ b/associations/associations_for_struct.go @@ -27,6 +27,11 @@ var associationBuilders = map[string]associationBuilder{} // it throws an error when it finds a field that does // not exist for a model. func ForStruct(s interface{}, fields ...string) (Associations, error) { + return forStruct(s, s, fields) +} + +// forStruct is a recursive helper that passes the root model down for embedded fields +func forStruct(parent, s interface{}, fields []string) (Associations, error) { t, v := getModelDefinition(s) if t.Kind() != reflect.Struct { return nil, fmt.Errorf("could not get struct associations: not a struct but %T", s) @@ -74,7 +79,20 @@ func ForStruct(s interface{}, fields ...string) (Associations, error) { // inline embedded field if f.Anonymous { - innerAssociations, err := ForStruct(v.Field(i).Interface(), fields...) + field := v.Field(i) + // we need field to be a pointer, so that we can later set the value + // if the embedded field is of type struct {...}, we have to take its address + if field.Kind() != reflect.Ptr { + field = field.Addr() + } + if fieldIsNil(field) { + // initialize zero value + field = reflect.New(field.Type().Elem()) + // we can only get in this case if v.Field(i) is a pointer type because it could not be nil otherwise + // => it is safe to set it here as is + v.Field(i).Set(field) + } + innerAssociations, err := forStruct(parent, field.Interface(), fields) if err != nil { return nil, err } @@ -92,11 +110,12 @@ func ForStruct(s interface{}, fields ...string) (Associations, error) { for name, builder := range associationBuilders { tag := tags.Find(name) if !tag.Empty() { + pt, pv := getModelDefinition(parent) params := associationParams{ field: f, - model: s, - modelType: t, - modelValue: v, + model: parent, + modelType: pt, + modelValue: pv, popTags: tags, innerAssociations: fieldsWithInnerAssociation[f.Name], } diff --git a/executors_test.go b/executors_test.go index d428e364..0f59baaa 100644 --- a/executors_test.go +++ b/executors_test.go @@ -1231,6 +1231,138 @@ func Test_Eager_Creation_Without_Associations(t *testing.T) { }) } +func Test_Eager_Embedded_Struct(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + type AssocFields struct { + Books Books `has_many:"books" order_by:"title asc"` + FavoriteSong Song `has_one:"song" fk_id:"u_id"` + Houses Addresses `many_to_many:"users_addresses"` + } + + type User struct { + ID int `db:"id"` + UserName string `db:"user_name"` + Name nulls.String `db:"name"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + + AssocFields + } + + count, _ := tx.Count(&User{}) + user := User{ + UserName: "dumb-dumb", + Name: nulls.NewString("Arthur Dent"), + AssocFields: AssocFields{ + Books: Books{{Title: "The Hitchhiker's Guide to the Galaxy", Description: "Comedy Science Fiction somewhere in Space", Isbn: "PB42"}}, + FavoriteSong: Song{Title: "Wish You Were Here", ComposedBy: Composer{Name: "Pink Floyd"}}, + Houses: Addresses{ + Address{HouseNumber: 155, Street: "Country Lane"}, + }, + }, + } + + err := tx.Eager().Create(&user) + r.NoError(err) + r.NotZero(user.ID) + + ctx, _ := tx.Count(&User{}) + r.Equal(count+1, ctx) + + ctx, _ = tx.Count(&Book{}) + r.Equal(count+1, ctx) + + ctx, _ = tx.Count(&Song{}) + r.Equal(count+1, ctx) + + ctx, _ = tx.Count(&Address{}) + r.Equal(count+1, ctx) + + u := User{} + q := tx.Eager().Where("name = ?", user.Name.String) + err = q.First(&u) + r.NoError(err) + + r.Equal(user.Name.String, u.Name.String) + r.Len(u.Books, 1) + r.Equal(user.Books[0].Title, u.Books[0].Title) + r.Equal(user.FavoriteSong.Title, u.FavoriteSong.Title) + r.Len(u.Houses, 1) + r.Equal(user.Houses[0].Street, u.Houses[0].Street) + }) +} + +func Test_Eager_Embedded_Ptr_Struct(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + type AssocFields struct { + Books Books `has_many:"books" order_by:"title asc"` + FavoriteSong Song `has_one:"song" fk_id:"u_id"` + Houses Addresses `many_to_many:"users_addresses"` + } + + type User struct { + ID int `db:"id"` + UserName string `db:"user_name"` + Name nulls.String `db:"name"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + + *AssocFields + } + + count, _ := tx.Count(&User{}) + user := User{ + UserName: "dumb-dumb", + Name: nulls.NewString("Arthur Dent"), + AssocFields: &AssocFields{ + Books: Books{{Title: "The Hitchhiker's Guide to the Galaxy", Description: "Comedy Science Fiction somewhere in Space", Isbn: "PB42"}}, + FavoriteSong: Song{Title: "Wish You Were Here", ComposedBy: Composer{Name: "Pink Floyd"}}, + Houses: Addresses{ + Address{HouseNumber: 155, Street: "Country Lane"}, + }, + }, + } + + err := tx.Eager().Create(&user) + r.NoError(err) + r.NotZero(user.ID) + + ctx, _ := tx.Count(&User{}) + r.Equal(count+1, ctx) + + ctx, _ = tx.Count(&Book{}) + r.Equal(count+1, ctx) + + ctx, _ = tx.Count(&Song{}) + r.Equal(count+1, ctx) + + ctx, _ = tx.Count(&Address{}) + r.Equal(count+1, ctx) + + u := User{} + q := tx.Eager().Where("name = ?", user.Name.String) + err = q.First(&u) + r.NoError(err) + + r.Equal(user.Name.String, u.Name.String) + r.Len(u.Books, 1) + r.Equal(user.Books[0].Title, u.Books[0].Title) + r.Equal(user.FavoriteSong.Title, u.FavoriteSong.Title) + r.Len(u.Houses, 1) + r.Equal(user.Houses[0].Street, u.Houses[0].Street) + }) +} + func Test_Create_UUID(t *testing.T) { if PDB == nil { t.Skip("skipping integration tests") From d60e1cfd48eb9445dae67c5d9d25ed8e2f0e1e17 Mon Sep 17 00:00:00 2001 From: zepatrik Date: Wed, 20 Apr 2022 16:57:43 +0300 Subject: [PATCH 46/59] test: add other fields to duplicate type, because of some kind of query builder cache --- docker-compose.yml | 4 ++-- executors_test.go | 32 ++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 54b90986..2201bec8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: mysql: @@ -25,7 +25,7 @@ services: - ./sqldumps:/docker-entrypoint-initdb.d cockroach: image: cockroachdb/cockroach:v20.2.4 - user: ${CURRENT_UID:?"Please run as follows 'CURRENT_UID=$(id -u):$(id -g) docker-compose up'"} + user: ${CURRENT_UID:?"Please run as follows 'CURRENT_UID=$$(id -u):$$(id -g) docker-compose up'"} ports: - "26257:26257" volumes: diff --git a/executors_test.go b/executors_test.go index 0f59baaa..e47e4d0a 100644 --- a/executors_test.go +++ b/executors_test.go @@ -1245,11 +1245,17 @@ func Test_Eager_Embedded_Struct(t *testing.T) { } type User struct { - ID int `db:"id"` - UserName string `db:"user_name"` - Name nulls.String `db:"name"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ID int `db:"id"` + UserName string `db:"user_name"` + Email string `db:"email"` + Name nulls.String `db:"name"` + Alive nulls.Bool `db:"alive"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + BirthDate nulls.Time `db:"birth_date"` + Bio nulls.String `db:"bio"` + Price nulls.Float64 `db:"price"` + FullName nulls.String `db:"full_name" select:"name as full_name"` AssocFields } @@ -1311,11 +1317,17 @@ func Test_Eager_Embedded_Ptr_Struct(t *testing.T) { } type User struct { - ID int `db:"id"` - UserName string `db:"user_name"` - Name nulls.String `db:"name"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ID int `db:"id"` + UserName string `db:"user_name"` + Email string `db:"email"` + Name nulls.String `db:"name"` + Alive nulls.Bool `db:"alive"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + BirthDate nulls.Time `db:"birth_date"` + Bio nulls.String `db:"bio"` + Price nulls.Float64 `db:"price"` + FullName nulls.String `db:"full_name" select:"name as full_name"` *AssocFields } From e6ba76ba3be301bf1f6a4f0cc4c24ae68f2de5af Mon Sep 17 00:00:00 2001 From: Grant Zvolsky Date: Thu, 14 Apr 2022 13:11:25 +0200 Subject: [PATCH 47/59] feat: implement UpdateQuery This commit introduces a new function, UpdateQuery, that enables updating all rows matched by a query. It can be used for conditional updates. --- dialect.go | 1 + dialect_cockroach.go | 4 ++ dialect_common.go | 27 +++++++++++ dialect_mysql.go | 9 ++++ dialect_postgresql.go | 4 ++ dialect_sqlite.go | 16 +++++++ executors.go | 29 ++++++++++++ executors_test.go | 108 ++++++++++++++++++++++++++++++++++++++++++ pop_test.go | 2 +- 9 files changed, 199 insertions(+), 1 deletion(-) diff --git a/dialect.go b/dialect.go index 1b87847d..0e49b168 100644 --- a/dialect.go +++ b/dialect.go @@ -12,6 +12,7 @@ type crudable interface { SelectMany(store, *Model, Query) error Create(store, *Model, columns.Columns) error Update(store, *Model, columns.Columns) error + UpdateQuery(store, *Model, columns.Columns, Query) (int64, error) Destroy(store, *Model) error Delete(store, *Model, Query) error } diff --git a/dialect_cockroach.go b/dialect_cockroach.go index 16d4d96b..5fb7e324 100644 --- a/dialect_cockroach.go +++ b/dialect_cockroach.go @@ -106,6 +106,10 @@ func (p *cockroach) Update(s store, model *Model, cols columns.Columns) error { return genericUpdate(s, model, cols, p) } +func (p *cockroach) UpdateQuery(s store, model *Model, cols columns.Columns, query Query) (int64, error) { + return genericUpdateQuery(s, model, cols, p, query, sqlx.DOLLAR) +} + func (p *cockroach) Destroy(s store, model *Model) error { stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", p.Quote(model.TableName()), model.Alias(), model.WhereID())) _, err := genericExec(s, stmt, model.ID()) diff --git a/dialect_common.go b/dialect_common.go index d0876295..5b1d76f4 100644 --- a/dialect_common.go +++ b/dialect_common.go @@ -14,6 +14,7 @@ import ( "github.com/gobuffalo/pop/v6/columns" "github.com/gobuffalo/pop/v6/logging" "github.com/gofrs/uuid" + "github.com/jmoiron/sqlx" ) func init() { @@ -110,6 +111,32 @@ func genericUpdate(s store, model *Model, cols columns.Columns, quoter quotable) return nil } +func genericUpdateQuery(s store, model *Model, cols columns.Columns, quoter quotable, query Query, bindType int) (int64, error) { + q := fmt.Sprintf("UPDATE %s AS %s SET %s", quoter.Quote(model.TableName()), model.Alias(), cols.Writeable().QuotedUpdateString(quoter)) + + q, updateArgs, err := sqlx.Named(q, model.Value) + if err != nil { + return 0, err + } + + sb := query.toSQLBuilder(model) + q = sb.buildWhereClauses(q) + + q = sqlx.Rebind(bindType, q) + + result, err := genericExec(s, q, append(updateArgs, sb.args...)...) + if err != nil { + return 0, err + } + + n, err := result.RowsAffected() + if err != nil { + return 0, err + } + + return n, err +} + func genericDestroy(s store, model *Model, quoter quotable) error { stmt := fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", quoter.Quote(model.TableName()), model.Alias(), model.WhereID()) _, err := genericExec(s, stmt, model.ID()) diff --git a/dialect_mysql.go b/dialect_mysql.go index 1cfda3cf..7b5022b4 100644 --- a/dialect_mysql.go +++ b/dialect_mysql.go @@ -13,6 +13,7 @@ import ( "github.com/gobuffalo/pop/v6/columns" "github.com/gobuffalo/pop/v6/internal/defaults" "github.com/gobuffalo/pop/v6/logging" + "github.com/jmoiron/sqlx" ) const nameMySQL = "mysql" @@ -94,6 +95,14 @@ func (m *mysql) Update(s store, model *Model, cols columns.Columns) error { return nil } +func (m *mysql) UpdateQuery(s store, model *Model, cols columns.Columns, query Query) (int64, error) { + if n, err := genericUpdateQuery(s, model, cols, m, query, sqlx.QUESTION); err != nil { + return n, fmt.Errorf("mysql update query: %w", err) + } else { + return n, nil + } +} + func (m *mysql) Destroy(s store, model *Model) error { stmt := fmt.Sprintf("DELETE FROM %s WHERE %s = ?", m.Quote(model.TableName()), model.IDField()) _, err := genericExec(s, stmt, model.ID()) diff --git a/dialect_postgresql.go b/dialect_postgresql.go index fe4d0236..6ce61569 100644 --- a/dialect_postgresql.go +++ b/dialect_postgresql.go @@ -90,6 +90,10 @@ func (p *postgresql) Update(s store, model *Model, cols columns.Columns) error { return genericUpdate(s, model, cols, p) } +func (p *postgresql) UpdateQuery(s store, model *Model, cols columns.Columns, query Query) (int64, error) { + return genericUpdateQuery(s, model, cols, p, query, sqlx.DOLLAR) +} + func (p *postgresql) Destroy(s store, model *Model) error { stmt := p.TranslateSQL(fmt.Sprintf("DELETE FROM %s AS %s WHERE %s", p.Quote(model.TableName()), model.Alias(), model.WhereID())) _, err := genericExec(s, stmt, model.ID()) diff --git a/dialect_sqlite.go b/dialect_sqlite.go index 1ac8691f..91dfce97 100644 --- a/dialect_sqlite.go +++ b/dialect_sqlite.go @@ -1,3 +1,4 @@ +//go:build sqlite // +build sqlite package pop @@ -19,6 +20,7 @@ import ( "github.com/gobuffalo/pop/v6/columns" "github.com/gobuffalo/pop/v6/internal/defaults" "github.com/gobuffalo/pop/v6/logging" + "github.com/jmoiron/sqlx" "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3" // Load SQLite3 CGo driver ) @@ -109,6 +111,20 @@ func (m *sqlite) Update(s store, model *Model, cols columns.Columns) error { }) } +func (m *sqlite) UpdateQuery(s store, model *Model, cols columns.Columns, query Query) (int64, error) { + rowsAffected := int64(0) + err := m.locker(m.smGil, func() error { + if n, err := genericUpdateQuery(s, model, cols, m, query, sqlx.QUESTION); err != nil { + rowsAffected = n + return fmt.Errorf("sqlite update query: %w", err) + } else { + rowsAffected = n + return nil + } + }) + return rowsAffected, err +} + func (m *sqlite) Destroy(s store, model *Model) error { return m.locker(m.smGil, func() error { if err := genericDestroy(s, model, m); err != nil { diff --git a/executors.go b/executors.go index 04478f66..37b03b35 100644 --- a/executors.go +++ b/executors.go @@ -380,6 +380,35 @@ func (c *Connection) Update(model interface{}, excludeColumns ...string) error { }) } +// UpdateQuery updates all rows matched by the query. The new values are read +// from the first argument, which must be a struct. The column names to be +// updated must be listed explicitly in subsequent arguments. The ID and +// CreatedAt columns are never updated. The UpdatedAt column is updated +// automatically. +// +// UpdateQuery does not execute (before|after)(Create|Update|Save) callbacks. +// +// Calling UpdateQuery with no columnNames will result in only the UpdatedAt +// column being updated. +func (q *Query) UpdateQuery(model interface{}, columnNames ...string) (int64, error) { + sm := NewModel(model, q.Connection.Context()) + modelKind := reflect.TypeOf(reflect.Indirect(reflect.ValueOf(model))).Kind() + if modelKind != reflect.Struct { + return 0, fmt.Errorf("model must be a struct; got %s", modelKind) + } + + cols := columns.NewColumnsWithAlias(sm.TableName(), sm.As, sm.IDField()) + cols.Add(columnNames...) + if _, err := sm.fieldByName("UpdatedAt"); err == nil { + cols.Add("updated_at") + } + cols.Remove(sm.IDField(), "created_at") + + now := nowFunc().Truncate(time.Microsecond) + sm.setUpdatedAt(now) + return q.Connection.Dialect.UpdateQuery(q.Connection.Store, sm, cols, *q) +} + // UpdateColumns writes changes from an entry to the database, including only the given columns // or all columns if no column names are provided. // It updates the `updated_at` column automatically if you include `updated_at` in columnNames. diff --git a/executors_test.go b/executors_test.go index e47e4d0a..d5154836 100644 --- a/executors_test.go +++ b/executors_test.go @@ -556,6 +556,13 @@ func Test_Embedded_Struct(t *testing.T) { r.NoError(tx.Find(&actual, entry.ID)) r.Equal(entry.AdditionalField, actual.AdditionalField) + entry.AdditionalField = entry.AdditionalField + "; updated again" + count, err := tx.Where("id = ?", entry.ID).UpdateQuery(entry, "additional_field") + r.NoError(err) + require.Equal(t, int64(1), count) + r.NoError(tx.Find(&actual, entry.ID)) + r.Equal(entry.AdditionalField, actual.AdditionalField) + r.NoError(tx.Destroy(entry)) }) } @@ -1493,6 +1500,107 @@ func Test_UpdateColumns(t *testing.T) { }) } +func Test_UpdateQuery_NoUpdatedAt(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + r.NoError(PDB.Create(&NonStandardID{OutfacingID: "must-change"})) + count, err := PDB.Where("true").UpdateQuery(&NonStandardID{OutfacingID: "has-changed"}, "id") + r.NoError(err) + r.Equal(int64(1), count) + entity := NonStandardID{} + r.NoError(PDB.First(&entity)) + r.Equal("has-changed", entity.OutfacingID) + }) +} + +func Test_UpdateQuery_NoTransaction(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + + r := require.New(t) + u1 := User{Name: nulls.NewString("Foo"), Bio: nulls.NewString("must-not-change-1")} + r.NoError(PDB.Create(&u1)) + r.NoError(PDB.Reload(&u1)) + count, err := PDB.Where("name = ?", "Nemo").UpdateQuery(&User{Bio: nulls.NewString("did-change")}, "bio") + r.NoError(err) + require.Equal(t, int64(0), count) + + count, err = PDB.Where("name = ?", "Foo").UpdateQuery(&User{Name: nulls.NewString("Bar")}, "name") + r.NoError(err) + r.Equal(int64(1), count) + + require.NoError(t, PDB.Destroy(&u1)) +} + +func Test_UpdateQuery(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + u1 := User{Name: nulls.NewString("Foo"), Bio: nulls.NewString("must-not-change-1")} + u2 := User{Name: nulls.NewString("Foo"), Bio: nulls.NewString("must-not-change-2")} + u3 := User{Name: nulls.NewString("Baz"), Bio: nulls.NewString("must-not-change-3")} + tx.Create(&u1) + tx.Create(&u2) + tx.Create(&u3) + r.NoError(tx.Reload(&u1)) + r.NoError(tx.Reload(&u2)) + r.NoError(tx.Reload(&u3)) + time.Sleep(time.Millisecond * 1) + + // No affected rows + count, err := tx.Where("name = ?", "Nemo").UpdateQuery(&User{Bio: nulls.NewString("did-change")}, "bio") + r.NoError(err) + require.Equal(t, int64(0), count) + mustUnchanged := &User{} + r.NoError(tx.Find(mustUnchanged, u1.ID)) + r.Equal(u1.Bio, mustUnchanged.Bio) + r.Equal(u1.UpdatedAt, mustUnchanged.UpdatedAt) + + // Correct rows are updated, including updated_at + count, err = tx.Where("name = ?", "Foo").UpdateQuery(&User{Name: nulls.NewString("Bar")}, "name") + r.NoError(err) + r.Equal(int64(2), count) + + u1b, u2b, u3b := &User{}, &User{}, &User{} + r.NoError(tx.Find(u1b, u1.ID)) + r.NoError(tx.Find(u2b, u2.ID)) + r.NoError(tx.Find(u3b, u3.ID)) + r.Equal(u1b.Name.String, "Bar") + r.Equal(u2b.Name.String, "Bar") + r.Equal(u3b.Name.String, "Baz") + r.Equal(u1b.Bio.String, "must-not-change-1") + r.Equal(u2b.Bio.String, "must-not-change-2") + r.Equal(u3b.Bio.String, "must-not-change-3") + if tx.Dialect.Name() != nameMySQL { // MySQL timestamps are in seconds + r.NotEqual(u1.UpdatedAt, u1b.UpdatedAt) + r.NotEqual(u2.UpdatedAt, u2b.UpdatedAt) + } + r.Equal(u3.UpdatedAt, u3b.UpdatedAt) + + // ID is ignored + count, err = tx.Where("true").UpdateQuery(&User{ID: 123, Name: nulls.NewString("Bar")}, "id", "name") + r.NoError(tx.Find(u1b, u1.ID)) + r.NoError(tx.Find(u2b, u2.ID)) + r.NoError(tx.Find(u3b, u3.ID)) + r.Equal(u1b.Name.String, "Bar") + r.Equal(u2b.Name.String, "Bar") + r.Equal(u3b.Name.String, "Bar") + + // Invalid column yields an error + count, err = tx.Where("name = ?", "Foo").UpdateQuery(&User{Name: nulls.NewString("Bar")}, "mistake") + r.Contains(err.Error(), "could not find name mistake") + + tx.Where("true").Delete(&User{}) + }) +} + func Test_UpdateColumns_UpdatedAt(t *testing.T) { if PDB == nil { t.Skip("skipping integration tests") diff --git a/pop_test.go b/pop_test.go index 629ea35a..95fd8648 100644 --- a/pop_test.go +++ b/pop_test.go @@ -52,7 +52,7 @@ func init() { dialect := os.Getenv("SODA_DIALECT") if dialect == "" { - log(logging.Info, "Skipping integration tests") + log(logging.Info, "Skipping integration tests because SODA_DIALECT is blank or unset") return } From d722117d51dc678bc01d19f11281b57a9f5fa9c4 Mon Sep 17 00:00:00 2001 From: Andrew Hobson Date: Thu, 21 Apr 2022 11:56:57 -0400 Subject: [PATCH 48/59] feat: allow customizing the time used for CreatedAt/UpdatedAt --- executors_test.go | 25 +++++++++++++++++++++++++ model.go | 5 +++++ 2 files changed, 30 insertions(+) diff --git a/executors_test.go b/executors_test.go index d5154836..ddafdb5a 100644 --- a/executors_test.go +++ b/executors_test.go @@ -1964,3 +1964,28 @@ func Test_Delete(t *testing.T) { r.Equal(count, ctx) }) } + +func Test_Create_Timestamps_With_NowFunc(t *testing.T) { + if PDB == nil { + t.Skip("skipping integration tests") + } + transaction(func(tx *Connection) { + r := require.New(t) + + originalNowFunc := nowFunc + // ensure the original function is restored + defer func() { + nowFunc = originalNowFunc + }() + + fakeNow, _ := time.Parse(time.RFC3339, "2019-07-14T00:00:00Z") + SetNowFunc(func() time.Time { return fakeNow }) + + friend:= Friend{FirstName: "Yester", LastName: "Day"} + err := tx.Create(&friend) + r.NoError(err) + + r.Equal(fakeNow, friend.CreatedAt) + r.Equal(fakeNow, friend.UpdatedAt) + }) +} diff --git a/model.go b/model.go index dddbec66..7b03d78f 100644 --- a/model.go +++ b/model.go @@ -15,6 +15,11 @@ import ( var nowFunc = time.Now +// SetNowFunc allows an override of time.Now for customizing CreatedAt/UpdatedAt +func SetNowFunc(f func() time.Time) { + nowFunc = f +} + // Value is the contents of a `Model`. type Value interface{} From 6abef98a293f0bd46d0e6d90a4f2152e9270451c Mon Sep 17 00:00:00 2001 From: Jonathan Duck Date: Fri, 22 Apr 2022 21:39:02 -0700 Subject: [PATCH 49/59] feat: allow using SQLite without built tag via include (#662) --- dialect_sqlite.go | 30 ++++++++++++++++++++++++------ dialect_sqlite_shim.go | 23 ----------------------- dialect_sqlite_tag.go | 8 ++++++++ 3 files changed, 32 insertions(+), 29 deletions(-) delete mode 100644 dialect_sqlite_shim.go create mode 100644 dialect_sqlite_tag.go diff --git a/dialect_sqlite.go b/dialect_sqlite.go index 91dfce97..d8400a50 100644 --- a/dialect_sqlite.go +++ b/dialect_sqlite.go @@ -1,10 +1,9 @@ -//go:build sqlite -// +build sqlite - package pop import ( + "database/sql" "database/sql/driver" + "errors" "fmt" "io" "net/url" @@ -21,8 +20,6 @@ import ( "github.com/gobuffalo/pop/v6/internal/defaults" "github.com/gobuffalo/pop/v6/logging" "github.com/jmoiron/sqlx" - "github.com/mattn/go-sqlite3" - _ "github.com/mattn/go-sqlite3" // Load SQLite3 CGo driver ) const nameSQLite3 = "sqlite3" @@ -43,6 +40,15 @@ type sqlite struct { smGil *sync.Mutex } +func requireSQLite3() error { + for _, driverName := range sql.Drivers() { + if driverName == nameSQLite3 { + return nil + } + } + return errors.New("sqlite3 support was not compiled into the binary") +} + func (m *sqlite) Name() string { return nameSQLite3 } @@ -263,6 +269,10 @@ func (m *sqlite) TruncateAll(tx *Connection) error { } func newSQLite(deets *ConnectionDetails) (dialect, error) { + err := requireSQLite3() + if err != nil { + return nil, err + } deets.URL = fmt.Sprintf("sqlite3://%s", deets.Database) cd := &sqlite{ gil: &sync.Mutex{}, @@ -328,5 +338,13 @@ func finalizerSQLite(cd *ConnectionDetails) { } func newSQLiteDriver() (driver.Driver, error) { - return new(sqlite3.SQLiteDriver), nil + err := requireSQLite3() + if err != nil { + return nil, err + } + db, err := sql.Open(nameSQLite3, ":memory:?cache=newSQLiteDriver_temporary") + if err != nil { + return nil, err + } + return db.Driver(), db.Close() } diff --git a/dialect_sqlite_shim.go b/dialect_sqlite_shim.go deleted file mode 100644 index 0c51baa1..00000000 --- a/dialect_sqlite_shim.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build !sqlite - -package pop - -import ( - "database/sql/driver" - "errors" -) - -const nameSQLite3 = "sqlite3" - -func init() { - dialectSynonyms["sqlite"] = nameSQLite3 - newConnection[nameSQLite3] = newSQLite -} - -func newSQLite(deets *ConnectionDetails) (dialect, error) { - return nil, errors.New("sqlite3 support was not compiled into the binary") -} - -func newSQLiteDriver() (driver.Driver, error) { - return nil, errors.New("sqlite3 support was not compiled into the binary") -} diff --git a/dialect_sqlite_tag.go b/dialect_sqlite_tag.go new file mode 100644 index 00000000..286dd783 --- /dev/null +++ b/dialect_sqlite_tag.go @@ -0,0 +1,8 @@ +//go:build sqlite +// +build sqlite + +package pop + +import ( + _ "github.com/mattn/go-sqlite3" // Load SQLite3 CGo driver +) From 11737925cf2800ee1b8a276be74a0d41666d481b Mon Sep 17 00:00:00 2001 From: Yonghwan SO Date: Fri, 13 May 2022 20:08:01 +0900 Subject: [PATCH 50/59] preparing go1.18 support (package specific workflow) --- .github/workflows/tests.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4e98acfe..d3f9c48e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,6 +14,7 @@ jobs: go-version: - "1.16.x" - "1.17.x" + - "1.18.x" services: mysql: @@ -57,6 +58,7 @@ jobs: go-version: - "1.16.x" - "1.17.x" + - "1.18.x" services: postgres: @@ -102,6 +104,7 @@ jobs: go-version: - "1.16.x" - "1.17.x" + - "1.18.x" steps: - uses: actions/checkout@v3 @@ -145,6 +148,7 @@ jobs: go-version: - "1.16.x" - "1.17.x" + - "1.18.x" steps: - uses: actions/checkout@v3 @@ -185,6 +189,7 @@ jobs: go-version: - "1.16.x" - "1.17.x" + - "1.18.x" os: - "macos-latest" - "windows-latest" From ca4f9fd51364297782811c1a24847306f59b3005 Mon Sep 17 00:00:00 2001 From: Joey Freeland <30938344+jfreeland@users.noreply.github.com> Date: Sat, 14 May 2022 20:50:58 -0400 Subject: [PATCH 51/59] feat: darwin arm64 binary (#690) * feat: arm64 binary * v6.0.2 (#704) * fix: improve model ID field customization (#604) Updates places where `"id"` was hardcoded instead of using `model.IDField()`. * Ensure uninitialized map is initialized when unmarshaling json Add tests for this scenario * exclude migration_table_name from connection string * add test for OptionsString * Add support for pointer FKs when preloading a belongs_to association (#602) * feat: support context-aware tablenames (#614) This patch adds a feature which enables pop to pass down the connection context to the model's TableName() function by implementing TableName(ctx context.Context) string. The context can be used to dynamically generate tablenames which can be important for prefixed or generic tables and other use cases. * Bump pg deps (#616) * Reset to development * bumping pgx and pgconn versions Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * Latest from master (#620) * Latest from development (#617) * fix: improve model ID field customization (#604) Updates places where `"id"` was hardcoded instead of using `model.IDField()`. * Ensure uninitialized map is initialized when unmarshaling json Add tests for this scenario * exclude migration_table_name from connection string * add test for OptionsString * Add support for pointer FKs when preloading a belongs_to association (#602) * feat: support context-aware tablenames (#614) This patch adds a feature which enables pop to pass down the connection context to the model's TableName() function by implementing TableName(ctx context.Context) string. The context can be used to dynamically generate tablenames which can be important for prefixed or generic tables and other use cases. * Bump pg deps (#616) * Reset to development * bumping pgx and pgconn versions Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * adding goreleaser syntaz (#619) Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * Resolve issues in UPDATE and DELETE when using schemas (#618) * Resolve MySQL issues and improve test migrations * Bump CockroachDB to maintained and supported versions Version 2.1 has reached EoL in 2019 Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Use `PaginatorPageKey` and `PaginatorPerPageKey` variables (#615) * update pagination_test * Pass Time structure into timestamp update functions. (#625) Closes #624 * Allow nullable JSONB and resolve MySQL regression (#639) * Allow passing args to `Order` (#630) * Added connection maximum idle time configuration (#635) This PR add the possibility to configure the connection maximum idle time (https://golang.org/pkg/database/sql/#DB.SetConnMaxIdleTime). Closes #632 BREAKING CHANGE: Requires Go 1.15 from now on. * Bump sqlite to 3.35.4 / 1.14.7 (#642) * Update pg, pgx, sqlx (#643) - `jackc/pgx` to version `v4.11.0`. - `jmoiron/sqlx` to version`v1.3.3` - `lib/pq` to version`v1.10.1` * Fix Inner has many associations when passing on multiple arguments (#633) * Fix Inner has many associations when passing on multiple arguments for inner fields * Fix broken tests * clean up extractFieldAndInnerFields function Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> * Remove many to many TX condition for EagerPreload (#645) * Remove the need to use Tx when loading many to many associations * replace TX access to create a new tx.Store.Transaction() object * Added fix/tests for has_many with pointer foreign key (#647) Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> * Export WhereID, Alias, WhereNamedID (#637) This patch export some model convenience functions which are useful when constructing queries outside of pop: custom updates, deletes, inserts, ... Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> * fix: log model values everywhere (#656) Some SQL logs were missing the values as argument. This adds all places * Add delete to query builder (#658) This allows writing delete queries without knowing the exact primary key or for composite keys. `Destroy` only allows to delete by primary key, but there are many cases where you want to delete multiple rows or by some other query than the ID. See #29 * Sort down migrations (#657) Basically, just reversing the up migration order does not work, as that puts "all" migrations before specific ones. Therefore, I added implemented the proper `Less` function for down migrations explicitly. Related #533 Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> * Preserve eager information when validating models (#664) (#665) Co-authored-by: Karl Haas * Migrate from packr to fs (#667) * Updating Pgx (#660) * adding goreleaser syntaz * updating pgx now really * Migrate from packr to fs * Migrate to v6 * Use old build tags * Update error handling * Fix error after rebase * Fix error handling * Fix filenames for embed Go 1.16 usage Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> * Task merging master (#669) * v5.3.4 (#644) * fix: improve model ID field customization (#604) Updates places where `"id"` was hardcoded instead of using `model.IDField()`. * Ensure uninitialized map is initialized when unmarshaling json Add tests for this scenario * exclude migration_table_name from connection string * add test for OptionsString * Add support for pointer FKs when preloading a belongs_to association (#602) * feat: support context-aware tablenames (#614) This patch adds a feature which enables pop to pass down the connection context to the model's TableName() function by implementing TableName(ctx context.Context) string. The context can be used to dynamically generate tablenames which can be important for prefixed or generic tables and other use cases. * Bump pg deps (#616) * Reset to development * bumping pgx and pgconn versions Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * Latest from master (#620) * Latest from development (#617) * fix: improve model ID field customization (#604) Updates places where `"id"` was hardcoded instead of using `model.IDField()`. * Ensure uninitialized map is initialized when unmarshaling json Add tests for this scenario * exclude migration_table_name from connection string * add test for OptionsString * Add support for pointer FKs when preloading a belongs_to association (#602) * feat: support context-aware tablenames (#614) This patch adds a feature which enables pop to pass down the connection context to the model's TableName() function by implementing TableName(ctx context.Context) string. The context can be used to dynamically generate tablenames which can be important for prefixed or generic tables and other use cases. * Bump pg deps (#616) * Reset to development * bumping pgx and pgconn versions Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * adding goreleaser syntaz (#619) Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan * Resolve issues in UPDATE and DELETE when using schemas (#618) * Resolve MySQL issues and improve test migrations * Bump CockroachDB to maintained and supported versions Version 2.1 has reached EoL in 2019 Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Use `PaginatorPageKey` and `PaginatorPerPageKey` variables (#615) * update pagination_test * Pass Time structure into timestamp update functions. (#625) Closes #624 * Allow nullable JSONB and resolve MySQL regression (#639) * Allow passing args to `Order` (#630) * Added connection maximum idle time configuration (#635) This PR add the possibility to configure the connection maximum idle time (https://golang.org/pkg/database/sql/#DB.SetConnMaxIdleTime). Closes #632 BREAKING CHANGE: Requires Go 1.15 from now on. * Bump sqlite to 3.35.4 / 1.14.7 (#642) * Update pg, pgx, sqlx (#643) - `jackc/pgx` to version `v4.11.0`. - `jmoiron/sqlx` to version`v1.3.3` - `lib/pq` to version`v1.10.1` * Fix Inner has many associations when passing on multiple arguments (#633) * Fix Inner has many associations when passing on multiple arguments for inner fields * Fix broken tests * clean up extractFieldAndInnerFields function Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> * Remove many to many TX condition for EagerPreload (#645) * Remove the need to use Tx when loading many to many associations * replace TX access to create a new tx.Store.Transaction() object * Added fix/tests for has_many with pointer foreign key (#647) Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Brian Buchholz <4773480+bhb603@users.noreply.github.com> Co-authored-by: Mike Pontillo Co-authored-by: Benjamin Blattberg Co-authored-by: Jonathan Duck Co-authored-by: Arthur Knoepflin * Updating Pgx (#660) * adding goreleaser syntaz * updating pgx now really * tidying Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Brian Buchholz <4773480+bhb603@users.noreply.github.com> Co-authored-by: Mike Pontillo Co-authored-by: Benjamin Blattberg Co-authored-by: Jonathan Duck Co-authored-by: Arthur Knoepflin * Replace removed command The command has been removed from the CLI. This patch introduces a new mechanism to reliably dump the SQL schema for CockroachDB. * Resolve `EagerPreload` panic caused for pointer references Resolves a panic where `EagerPreload` tried to set `reflect.Struct` for a `reflect.Pointer` on 1.. associations. Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Resolve `EagerPreload` panic caused by NullUUID Resolves a panic where `EagerPreload` was trying to set UUID into NullUUID. Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Support pointers in n+1 `Eager` loading Resolves an issue where n+1 eager associations would error with a double pointer in `associations.ForStruct`. Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Improve error message of associations.ForStruct Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Add test cases for `IsZeroOfUnderlyingType` Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Resolve an obscure bug where empty structs got loaded for NULL foreign keys Closes https://github.com/gobuffalo/pop/issues/139 Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Resolve association regression in finders.go Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Use dedicated migrations for preloading regression test Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Fix code regression Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Fix test code regressions Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Fix sql migration order Signed-off-by: aeneasr <3372410+aeneasr@users.noreply.github.com> * Resolve order issue in test * Ignore order when testing for nil values in test * Pass Context during exec in create. (#688) * feat: support embedded struct fields (#691) * test: use `T.TempDir` to create temporary test directory This commit replaces `ioutil.TempDir` with `t.TempDir` in tests. The directory created by `t.TempDir` is automatically removed when the test and all its subtests complete. Prior to this commit, temporary directory created using `ioutil.TempDir` needs to be removed manually by calling `os.RemoveAll`, which is omitted in some tests. The error handling boilerplate e.g. defer func() { if err := os.RemoveAll(dir); err != nil { t.Fatal(err) } } is also tedious, but `t.TempDir` handles this for us nicely. Reference: https://pkg.go.dev/testing#T.TempDir Signed-off-by: Eng Zer Jun * task: adding next version number Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Brian Buchholz <4773480+bhb603@users.noreply.github.com> Co-authored-by: Mike Pontillo Co-authored-by: Benjamin Blattberg Co-authored-by: Jonathan Duck Co-authored-by: Arthur Knoepflin Co-authored-by: karlhaas Co-authored-by: Karl Haas Co-authored-by: Matthias Fasching Co-authored-by: Martin Eigenbrodt Co-authored-by: Eng Zer Jun * play time * chore: updates * chore: reset formatting Co-authored-by: Antonio Pagano <645522+paganotoni@users.noreply.github.com> Co-authored-by: Patrik Co-authored-by: Michael Montgomery Co-authored-by: kyrozetera Co-authored-by: Reggie Riser <4960757+reggieriser@users.noreply.github.com> Co-authored-by: hackerman <3372410+aeneasr@users.noreply.github.com> Co-authored-by: Stanislas Michalak Co-authored-by: Larry M Jordan Co-authored-by: Brian Buchholz <4773480+bhb603@users.noreply.github.com> Co-authored-by: Mike Pontillo Co-authored-by: Benjamin Blattberg Co-authored-by: Jonathan Duck Co-authored-by: Arthur Knoepflin Co-authored-by: karlhaas Co-authored-by: Karl Haas Co-authored-by: Matthias Fasching Co-authored-by: Martin Eigenbrodt Co-authored-by: Eng Zer Jun --- .github/workflows/release.yml | 24 ++++++++++---------- .goreleaser.yml | 22 ++++++++++++++++--- Makefile | 41 ++++++++++++++++++++++++++++++++++- executors_test.go | 1 + 4 files changed, 73 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4eb7821c..e974c1ce 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,22 +9,24 @@ jobs: name: Release runs-on: ubuntu-latest steps: + - name: Checkout Code + uses: actions/checkout@v3 + - name: Set up Go 1.17 uses: actions/setup-go@v3 with: go-version: 1.17 - id: go - - - name: Checkout Code - uses: actions/checkout@v3 - name: Fetch tags run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v2 - env: - GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN }} - with: - version: latest - args: release --rm-dist + - name: release dry run + run: make release-dry-run + + - name: setup release environment + run: |- + echo 'GITHUB_TOKEN=${{secrets.GORELEASER_GITHUB_TOKEN }}' > .release-env + + - name: release publish + run: make release + diff --git a/.goreleaser.yml b/.goreleaser.yml index f22cfd3f..5588bc8a 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,5 +1,6 @@ # GoReleaser config +--- before: hooks: - go mod tidy @@ -14,17 +15,32 @@ builds: - amd64 env: - CGO_ENABLED=1 - - CC=o64-clang - - CXX=o64-clang++ + - CC=/osxcross/target/bin/o64-clang + - CXX=/osxcross/target/bin/o64-clang++ flags: - -tags - sqlite -- id: pop_linux +- id: pop_darwin_arm64 binary: soda main: soda/main.go + goos: + - darwin + goarch: + - arm64 env: - CGO_ENABLED=1 + - CC=/osxcross/target/bin/oa64-clang + - CXX=/osxcross/target/bin/oa64-clang++ + flags: + - -tags + - sqlite + +- id: pop_linux + binary: soda + main: soda/main.go + env: + - CGO_ENABLED=0 flags: - -tags - sqlite diff --git a/Makefile b/Makefile index 893e46e8..5bced524 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +PACKAGE_NAME := github.com/gobuffalo/pop +GOLANG_CROSS_VERSION ?= v1.17.6 + TAGS ?= "sqlite" GO_BIN ?= go @@ -37,5 +40,41 @@ endif release-test: ./test.sh +.PHONY: sysroot-pack +sysroot-pack: + @tar cf - $(SYSROOT_DIR) -P | pv -s $[$(du -sk $(SYSROOT_DIR) | awk '{print $1}') * 1024] | pbzip2 > $(SYSROOT_ARCHIVE) + +.PHONY: sysroot-unpack +sysroot-unpack: + @pv $(SYSROOT_ARCHIVE) | pbzip2 -cd | tar -xf - + +.PHONY: release-dry-run +release-dry-run: + @docker run \ + --rm \ + --privileged \ + -e CGO_ENABLED=1 \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v `pwd`:/go/src/$(PACKAGE_NAME) \ + -v `pwd`/sysroot:/sysroot \ + -w /go/src/$(PACKAGE_NAME) \ + goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \ + --rm-dist --skip-validate --skip-publish --snapshot + +.PHONY: release release: - release -y -f soda/cmd/version.go + @if [ ! -f ".release-env" ]; then \ + echo "\033[91m.release-env is required for release\033[0m";\ + exit 1;\ + fi + docker run \ + --rm \ + --privileged \ + -e CGO_ENABLED=1 \ + --env-file .release-env \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v `pwd`:/go/src/$(PACKAGE_NAME) \ + -v `pwd`/sysroot:/sysroot \ + -w /go/src/$(PACKAGE_NAME) \ + goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \ + release --rm-dist diff --git a/executors_test.go b/executors_test.go index ddafdb5a..e03ee2e3 100644 --- a/executors_test.go +++ b/executors_test.go @@ -556,6 +556,7 @@ func Test_Embedded_Struct(t *testing.T) { r.NoError(tx.Find(&actual, entry.ID)) r.Equal(entry.AdditionalField, actual.AdditionalField) + entry.AdditionalField = entry.AdditionalField + "; updated again" count, err := tx.Where("id = ?", entry.ID).UpdateQuery(entry, "additional_field") r.NoError(err) From e3075ecc63bcc16309c20ad53e12ba0def7c0c4a Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Sat, 14 May 2022 21:01:50 -0400 Subject: [PATCH 52/59] task: adding release-env in the gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d587321e..8365932b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ testdata/migrations/schema.sql .grifter/ vendor/ .env +.relenase-env # test data cockroach-data/ From d87f42d0e4b9003c1f57b0c7687742be28d03823 Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Sat, 14 May 2022 21:02:20 -0400 Subject: [PATCH 53/59] task: its release-env --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8365932b..74d9ca99 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,7 @@ testdata/migrations/schema.sql .grifter/ vendor/ .env -.relenase-env +.release-env # test data cockroach-data/ From 26aa9b0184deb16be42648af3251969c0b1b90f4 Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Sat, 14 May 2022 21:40:42 -0400 Subject: [PATCH 54/59] task: adding .release-env to the release-dry-run make --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 5bced524..24d4eab5 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,7 @@ release-dry-run: --rm \ --privileged \ -e CGO_ENABLED=1 \ + --env-file .release-env \ -v /var/run/docker.sock:/var/run/docker.sock \ -v `pwd`:/go/src/$(PACKAGE_NAME) \ -v `pwd`/sysroot:/sysroot \ From b62eb16931c03393c5b22c304c86b18d58f68e74 Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Sat, 14 May 2022 21:44:36 -0400 Subject: [PATCH 55/59] task: changing the order of release steps --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e974c1ce..a5106d68 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,13 +20,13 @@ jobs: - name: Fetch tags run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - - name: release dry run - run: make release-dry-run - - name: setup release environment run: |- echo 'GITHUB_TOKEN=${{secrets.GORELEASER_GITHUB_TOKEN }}' > .release-env + - name: release dry run + run: make release-dry-run + - name: release publish run: make release From 34037d1cdac6f18098574ff5f8b446b3b0c00b9b Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Sat, 14 May 2022 22:03:47 -0400 Subject: [PATCH 56/59] task:changing the token --- .github/workflows/release.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a5106d68..d9ca426f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,10 +22,7 @@ jobs: - name: setup release environment run: |- - echo 'GITHUB_TOKEN=${{secrets.GORELEASER_GITHUB_TOKEN }}' > .release-env - - - name: release dry run - run: make release-dry-run + echo 'GITHUB_TOKEN=${{secrets.GORELEASER_TOKEN }}' > .release-env - name: release publish run: make release From db86847bd4be632e90f37a204f023ee7e204edbb Mon Sep 17 00:00:00 2001 From: Antonio Pagano <645522+paganotoni@users.noreply.github.com> Date: Fri, 20 May 2022 20:43:12 -0500 Subject: [PATCH 57/59] feature: supporting sqlite :memory: and mode=memory on the sqlite driver (#717) --- .gitignore | 1 + dialect_sqlite.go | 24 +++++++++++++------ dialect_sqlite_test.go | 52 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 74d9ca99..bd494e42 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ testdata/migrations/schema.sql vendor/ .env .release-env +.vscode # test data cockroach-data/ diff --git a/dialect_sqlite.go b/dialect_sqlite.go index d8400a50..35647c3b 100644 --- a/dialect_sqlite.go +++ b/dialect_sqlite.go @@ -182,22 +182,32 @@ func (m *sqlite) locker(l *sync.Mutex, fn func() error) error { } func (m *sqlite) CreateDB() error { - _, err := os.Stat(m.ConnectionDetails.Database) + durl := m.ConnectionDetails.Database + + // Checking whether the url specifies in-memory mode + // as specified in https://github.com/mattn/go-sqlite3#faq + if strings.Contains(durl, ":memory:") || strings.Contains(durl, "mode=memory") { + log(logging.Info, "in memory db selected, no database file created.") + + return nil + } + + _, err := os.Stat(durl) if err == nil { - return fmt.Errorf("could not create SQLite database '%s'; database exists", m.ConnectionDetails.Database) + return fmt.Errorf("could not create SQLite database '%s'; database exists", durl) } - dir := filepath.Dir(m.ConnectionDetails.Database) + dir := filepath.Dir(durl) err = os.MkdirAll(dir, 0766) if err != nil { - return fmt.Errorf("could not create SQLite database '%s': %w", m.ConnectionDetails.Database, err) + return fmt.Errorf("could not create SQLite database '%s': %w", durl, err) } - f, err := os.Create(m.ConnectionDetails.Database) + f, err := os.Create(durl) if err != nil { - return fmt.Errorf("could not create SQLite database '%s': %w", m.ConnectionDetails.Database, err) + return fmt.Errorf("could not create SQLite database '%s': %w", durl, err) } _ = f.Close() - log(logging.Info, "created database '%s'", m.ConnectionDetails.Database) + log(logging.Info, "created database '%s'", durl) return nil } diff --git a/dialect_sqlite_test.go b/dialect_sqlite_test.go index 83a0294a..ac5db21a 100644 --- a/dialect_sqlite_test.go +++ b/dialect_sqlite_test.go @@ -1,3 +1,4 @@ +//go:build sqlite // +build sqlite package pop @@ -144,18 +145,51 @@ func Test_ConnectionDetails_FinalizeOSPath(t *testing.T) { func TestSqlite_CreateDB(t *testing.T) { r := require.New(t) - dir := t.TempDir() - p := filepath.Join(dir, "testdb.sqlite") - cd := &ConnectionDetails{ - Dialect: "sqlite", - Database: p, - } + + cd := &ConnectionDetails{Dialect: "sqlite"} dialect, err := newSQLite(cd) r.NoError(err) - r.NoError(dialect.CreateDB()) - // Creating DB twice should produce an error - r.EqualError(dialect.CreateDB(), fmt.Sprintf("could not create SQLite database '%s'; database exists", p)) + t.Run("CreateFile", func(t *testing.T) { + dir := t.TempDir() + cd.Database = filepath.Join(dir, "testdb.sqlite") + + r.NoError(dialect.CreateDB()) + r.FileExists(cd.Database) + }) + + t.Run("MemoryDB_tag", func(t *testing.T) { + dir := t.TempDir() + cd.Database = filepath.Join(dir, "file::memory:?cache=shared") + + r.NoError(dialect.CreateDB()) + r.NoFileExists(cd.Database) + }) + + t.Run("MemoryDB_only", func(t *testing.T) { + dir := t.TempDir() + cd.Database = filepath.Join(dir, ":memory:") + + r.NoError(dialect.CreateDB()) + r.NoFileExists(cd.Database) + }) + + t.Run("MemoryDB_param", func(t *testing.T) { + dir := t.TempDir() + cd.Database = filepath.Join(dir, "file:foobar?mode=memory&cache=shared") + + r.NoError(dialect.CreateDB()) + r.NoFileExists(cd.Database) + }) + + t.Run("CreateFile_ExistingDB", func(t *testing.T) { + dir := t.TempDir() + cd.Database = filepath.Join(dir, "testdb.sqlite") + + r.NoError(dialect.CreateDB()) + r.EqualError(dialect.CreateDB(), fmt.Sprintf("could not create SQLite database '%s'; database exists", cd.Database)) + }) + } func TestSqlite_NewDriver(t *testing.T) { From 012ea29c84cd38dd0e2b858eab58e8f6b7e161c4 Mon Sep 17 00:00:00 2001 From: Patrik Date: Thu, 19 May 2022 16:13:23 +0200 Subject: [PATCH 58/59] feat: expose connection transactions with context and options --- connection.go | 20 +++++++++++++------- connection_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/connection.go b/connection.go index f8b81d31..ecb3e87c 100644 --- a/connection.go +++ b/connection.go @@ -2,6 +2,7 @@ package pop import ( "context" + "database/sql" "errors" "fmt" "sync/atomic" @@ -185,21 +186,26 @@ func (c *Connection) Rollback(fn func(tx *Connection)) error { // NewTransaction starts a new transaction on the connection func (c *Connection) NewTransaction() (*Connection, error) { + return c.NewTransactionContextOptions(c.Context(), nil) +} + +// NewTransactionContext starts a new transaction on the connection using the provided context +func (c *Connection) NewTransactionContext(ctx context.Context) (*Connection, error) { + return c.NewTransactionContextOptions(ctx, nil) +} + +// NewTransactionContextOptions starts a new transaction on the connection using the provided context and transaction options +func (c *Connection) NewTransactionContextOptions(ctx context.Context, options *sql.TxOptions) (*Connection, error) { var cn *Connection if c.TX == nil { - tx, err := c.Store.Transaction() + tx, err := c.Store.TransactionContextOptions(ctx, options) if err != nil { return cn, fmt.Errorf("couldn't start a new transaction: %w", err) } - var store store = tx - // Rewrap the store if it was a context store - if cs, ok := c.Store.(contextStore); ok { - store = contextStore{store: store, ctx: cs.ctx} - } cn = &Connection{ ID: randx.String(30), - Store: store, + Store: contextStore{store: tx, ctx: ctx}, Dialect: c.Dialect, TX: tx, } diff --git a/connection_test.go b/connection_test.go index dfdb9756..a923a281 100644 --- a/connection_test.go +++ b/connection_test.go @@ -1,8 +1,10 @@ +//go:build sqlite // +build sqlite package pop import ( + "context" "testing" "github.com/stretchr/testify/require" @@ -52,3 +54,46 @@ func Test_Connection_Open_BadDriver(t *testing.T) { err = c.Open() r.Error(err) } + +func Test_Connection_Transaction(t *testing.T) { + r := require.New(t) + ctx := context.WithValue(context.Background(), "test", "test") + + c, err := NewConnection(&ConnectionDetails{ + URL: "sqlite://file::memory:?_fk=true", + }) + r.NoError(err) + r.NoError(c.Open()) + c = c.WithContext(ctx) + + t.Run("func=NewTransaction", func(t *testing.T) { + r := require.New(t) + tx, err := c.NewTransaction() + r.NoError(err) + + // has transaction and context + r.NotNil(tx.TX) + r.Nil(c.TX) + r.Equal(ctx, tx.Context()) + + // does not start a new transaction + ntx, err := tx.NewTransaction() + r.Equal(tx, ntx) + + r.NoError(tx.TX.Rollback()) + }) + + t.Run("func=NewTransactionContext", func(t *testing.T) { + r := require.New(t) + nctx := context.WithValue(ctx, "nested", "test") + tx, err := c.NewTransactionContext(nctx) + r.NoError(err) + + // has transaction and context + r.NotNil(tx.TX) + r.Nil(c.TX) + r.Equal(nctx, tx.Context()) + + r.NoError(tx.TX.Rollback()) + }) +} From 57fe58cb79bdf04ba84331c869f8aa40cac9752b Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Tue, 24 May 2022 09:46:53 -0500 Subject: [PATCH 59/59] task: adding vscode to the ignore list --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 74d9ca99..efb00cf9 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ testdata/migrations/schema.sql vendor/ .env .release-env +.vscode/ # test data cockroach-data/