Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 373bec7

Browse files
committed
entc/gen: allow opening and testing concurrent enttest clients
1 parent abefaa7 commit 373bec7

File tree

71 files changed

+783
-614
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+783
-614
lines changed

dialect/sql/schema/migrate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func (f CreateFunc) Create(ctx context.Context, tables ...*Table) error {
104104
return f(ctx, tables...)
105105
}
106106

107-
// Migrate runs the migrations logic for the SQL dialects.
107+
// Migrate runs the migration logic for the SQL dialects.
108108
type Migrate struct {
109109
sqlDialect
110110
universalID bool // global unique ids.

dialect/sql/schema/schema.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,96 @@ func (t *Table) fk(symbol string) (*ForeignKey, bool) {
173173
return nil, false
174174
}
175175

176+
// CopyTables returns a deep-copy of the given tables. This utility function is
177+
// useful for copying the generated schema tables (i.e. migrate.Tables) before
178+
// running schema migration when there is a need for execute multiple migrations
179+
// concurrently. e.g. running parallel unit-tests using the generated enttest package.
180+
func CopyTables(tables []*Table) ([]*Table, error) {
181+
var (
182+
copyT = make([]*Table, len(tables))
183+
byName = make(map[string]*Table)
184+
)
185+
for i, t := range tables {
186+
copyT[i] = &Table{
187+
Name: t.Name,
188+
Columns: make([]*Column, len(t.Columns)),
189+
Indexes: make([]*Index, len(t.Indexes)),
190+
ForeignKeys: make([]*ForeignKey, len(t.ForeignKeys)),
191+
}
192+
for j, c := range t.Columns {
193+
cc := *c
194+
// SchemaType and Enums are read-only fields.
195+
cc.indexes = nil
196+
cc.foreign = nil
197+
copyT[i].Columns[j] = &cc
198+
}
199+
if at := t.Annotation; at != nil {
200+
cat := *at
201+
copyT[i].Annotation = &cat
202+
}
203+
byName[t.Name] = copyT[i]
204+
}
205+
for i, t := range tables {
206+
ct := copyT[i]
207+
for _, c := range t.PrimaryKey {
208+
cc, ok := ct.column(c.Name)
209+
if !ok {
210+
return nil, fmt.Errorf("sql/schema: missing primary key column %q", c.Name)
211+
}
212+
ct.PrimaryKey = append(ct.PrimaryKey, cc)
213+
}
214+
for j, idx := range t.Indexes {
215+
cidx := &Index{
216+
Name: idx.Name,
217+
Unique: idx.Unique,
218+
Columns: make([]*Column, len(idx.Columns)),
219+
}
220+
if at := idx.Annotation; at != nil {
221+
cat := *at
222+
cidx.Annotation = &cat
223+
}
224+
for k, c := range idx.Columns {
225+
cc, ok := ct.column(c.Name)
226+
if !ok {
227+
return nil, fmt.Errorf("sql/schema: missing index column %q", c.Name)
228+
}
229+
cidx.Columns[k] = cc
230+
}
231+
ct.Indexes[j] = cidx
232+
}
233+
for j, fk := range t.ForeignKeys {
234+
cfk := &ForeignKey{
235+
Symbol: fk.Symbol,
236+
OnUpdate: fk.OnUpdate,
237+
OnDelete: fk.OnDelete,
238+
Columns: make([]*Column, len(fk.Columns)),
239+
RefColumns: make([]*Column, len(fk.RefColumns)),
240+
}
241+
for k, c := range fk.Columns {
242+
cc, ok := ct.column(c.Name)
243+
if !ok {
244+
return nil, fmt.Errorf("sql/schema: missing foreign-key column %q", c.Name)
245+
}
246+
cfk.Columns[k] = cc
247+
}
248+
cref, ok := byName[fk.RefTable.Name]
249+
if !ok {
250+
return nil, fmt.Errorf("sql/schema: missing foreign-key ref-table %q", fk.RefTable.Name)
251+
}
252+
cfk.RefTable = cref
253+
for k, c := range fk.RefColumns {
254+
cc, ok := cref.column(c.Name)
255+
if !ok {
256+
return nil, fmt.Errorf("sql/schema: missing foreign-key ref-column %q", c.Name)
257+
}
258+
cfk.RefColumns[k] = cc
259+
}
260+
ct.ForeignKeys[j] = cfk
261+
}
262+
}
263+
return copyT, nil
264+
}
265+
176266
// Column schema definition for SQL dialects.
177267
type Column struct {
178268
Name string // column name.

dialect/sql/schema/schema_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package schema
77
import (
88
"testing"
99

10+
"entgo.io/ent/dialect/entsql"
1011
"entgo.io/ent/schema/field"
1112

1213
"github.com/stretchr/testify/require"
@@ -101,3 +102,50 @@ func TestColumn_ScanDefault(t *testing.T) {
101102
require.NoError(t, c1.ScanDefault("00000000-0000-0000-0000-000000000000"))
102103
require.Equal(t, "00000000-0000-0000-0000-000000000000", c1.Default)
103104
}
105+
106+
func TestCopyTables(t *testing.T) {
107+
users := &Table{
108+
Name: "users",
109+
Columns: []*Column{
110+
{Name: "id", Type: field.TypeInt},
111+
{Name: "name", Type: field.TypeString},
112+
{Name: "spouse_id", Type: field.TypeInt},
113+
},
114+
}
115+
users.PrimaryKey = users.Columns[:1]
116+
users.Indexes = append(users.Indexes, &Index{
117+
Name: "name",
118+
Columns: users.Columns[1:2],
119+
})
120+
users.AddForeignKey(&ForeignKey{
121+
Columns: users.Columns[2:],
122+
RefTable: users,
123+
RefColumns: users.Columns[:1],
124+
OnUpdate: SetNull,
125+
})
126+
users.SetAnnotation(&entsql.Annotation{Table: "Users"})
127+
pets := &Table{
128+
Name: "pets",
129+
Columns: []*Column{
130+
{Name: "id", Type: field.TypeInt},
131+
{Name: "name", Type: field.TypeString},
132+
{Name: "owner_id", Type: field.TypeInt},
133+
},
134+
}
135+
pets.Indexes = append(pets.Indexes, &Index{
136+
Name: "name",
137+
Unique: true,
138+
Columns: pets.Columns[1:2],
139+
Annotation: entsql.Desc(),
140+
})
141+
pets.AddForeignKey(&ForeignKey{
142+
Columns: pets.Columns[2:],
143+
RefTable: users,
144+
RefColumns: users.Columns[:1],
145+
OnDelete: SetDefault,
146+
})
147+
tables := []*Table{users, pets}
148+
copyT, err := CopyTables(tables)
149+
require.NoError(t, err)
150+
require.Equal(t, tables, copyT)
151+
}

entc/gen/template/enttest.tmpl

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
_ "{{ $.Config.Package }}/runtime"
2323

2424
{{ if $.SupportMigrate }}
25+
"{{ $.Config.Package }}/migrate"
2526
"entgo.io/ent/dialect/sql/schema"
2627
{{ end }}
2728
)
@@ -78,10 +79,7 @@ func Open(t TestingT, driverName, dataSourceName string, opts ...Option) *{{ $pk
7879
t.FailNow()
7980
}
8081
{{- if $.SupportMigrate }}
81-
if err := c.Schema.Create(context.Background(), o.migrateOpts...); err != nil {
82-
t.Error(err)
83-
t.FailNow()
84-
}
82+
migrateSchema(t, c, o)
8583
{{- end }}
8684
return c
8785
}
@@ -91,12 +89,22 @@ func NewClient(t TestingT, opts ...Option) *{{ $pkg }}.Client {
9189
o := newOptions(opts)
9290
c := {{ $pkg }}.NewClient(o.opts...)
9391
{{- if $.SupportMigrate }}
94-
if err := c.Schema.Create(context.Background(), o.migrateOpts...); err != nil {
95-
t.Error(err)
96-
t.FailNow()
97-
}
92+
migrateSchema(t, c, o)
9893
{{- end }}
9994
return c
10095
}
10196

97+
{{- if $.SupportMigrate }}
98+
func migrateSchema(t TestingT, c *{{ $pkg }}.Client, o *options) {
99+
tables, err := schema.CopyTables(migrate.Tables)
100+
if err != nil {
101+
t.Error(err)
102+
t.FailNow()
103+
}
104+
if err := migrate.Create(context.Background(), c.Schema, tables, o.migrateOpts...); err != nil {
105+
t.Error(err)
106+
t.FailNow()
107+
}
108+
}
109+
{{- end }}
102110
{{ end }}

entc/gen/template/migrate/migrate.tmpl

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ var (
3737
// and therefore, it's recommended to enable this option to get more
3838
// flexibility in the schema changes.
3939
WithDropIndex = schema.WithDropIndex
40-
// WithFixture sets the foreign-key renaming option to the migration when upgrading
41-
// ent from v0.1.0 (issue-#285). Defaults to false.
42-
WithFixture = schema.WithFixture
4340
// WithForeignKeys enables creating foreign-key in schema DDL. This defaults to true.
4441
WithForeignKeys = schema.WithForeignKeys
4542
)
@@ -54,11 +51,16 @@ func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} }
5451

5552
// Create creates all schema resources.
5653
func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error {
54+
return Create(ctx, s, Tables, opts...)
55+
}
56+
57+
// Create creates all table resources using the given schema driver.
58+
func Create(ctx context.Context, s *Schema, tables []*schema.Table, opts ...schema.MigrateOption) error {
5759
migrate, err := schema.NewMigrate(s.drv, opts...)
5860
if err != nil {
5961
return fmt.Errorf("ent/migrate: %w", err)
6062
}
61-
return migrate.Create(ctx, Tables...)
63+
return migrate.Create(ctx, tables...)
6264
}
6365

6466
{{ if $.Config.FeatureEnabled "sql/versioned-migration" }}{{ template "migrate/diff" $ }}{{ end }}
@@ -70,14 +72,6 @@ func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error
7072
// }
7173
//
7274
func (s *Schema) WriteTo(ctx context.Context, w io.Writer, opts ...schema.MigrateOption) error {
73-
drv := &schema.WriteDriver{
74-
Writer: w,
75-
Driver: s.drv,
76-
}
77-
migrate, err := schema.NewMigrate(drv, opts...)
78-
if err != nil {
79-
return fmt.Errorf("ent/migrate: %w", err)
80-
}
81-
return migrate.Create(ctx, Tables...)
75+
return Create(ctx, &Schema{drv: &schema.WriteDriver{Writer: w, Driver: s.drv,}}, Tables, opts...)
8276
}
8377
{{ end }}

entc/integration/cascadelete/ent/enttest/enttest.go

Lines changed: 12 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

entc/integration/cascadelete/ent/migrate/migrate.go

Lines changed: 7 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

entc/integration/config/ent/enttest/enttest.go

Lines changed: 12 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)