mirror of
https://github.com/ent/ent.git
synced 2026-05-22 09:31:45 +03:00
entc/gen: allow opening and testing concurrent enttest clients (#2665)
This commit is contained in:
@@ -104,7 +104,7 @@ func (f CreateFunc) Create(ctx context.Context, tables ...*Table) error {
|
||||
return f(ctx, tables...)
|
||||
}
|
||||
|
||||
// Migrate runs the migrations logic for the SQL dialects.
|
||||
// Migrate runs the migration logic for the SQL dialects.
|
||||
type Migrate struct {
|
||||
sqlDialect
|
||||
universalID bool // global unique ids.
|
||||
|
||||
@@ -173,6 +173,96 @@ func (t *Table) fk(symbol string) (*ForeignKey, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// CopyTables returns a deep-copy of the given tables. This utility function is
|
||||
// useful for copying the generated schema tables (i.e. migrate.Tables) before
|
||||
// running schema migration when there is a need for execute multiple migrations
|
||||
// concurrently. e.g. running parallel unit-tests using the generated enttest package.
|
||||
func CopyTables(tables []*Table) ([]*Table, error) {
|
||||
var (
|
||||
copyT = make([]*Table, len(tables))
|
||||
byName = make(map[string]*Table)
|
||||
)
|
||||
for i, t := range tables {
|
||||
copyT[i] = &Table{
|
||||
Name: t.Name,
|
||||
Columns: make([]*Column, len(t.Columns)),
|
||||
Indexes: make([]*Index, len(t.Indexes)),
|
||||
ForeignKeys: make([]*ForeignKey, len(t.ForeignKeys)),
|
||||
}
|
||||
for j, c := range t.Columns {
|
||||
cc := *c
|
||||
// SchemaType and Enums are read-only fields.
|
||||
cc.indexes = nil
|
||||
cc.foreign = nil
|
||||
copyT[i].Columns[j] = &cc
|
||||
}
|
||||
if at := t.Annotation; at != nil {
|
||||
cat := *at
|
||||
copyT[i].Annotation = &cat
|
||||
}
|
||||
byName[t.Name] = copyT[i]
|
||||
}
|
||||
for i, t := range tables {
|
||||
ct := copyT[i]
|
||||
for _, c := range t.PrimaryKey {
|
||||
cc, ok := ct.column(c.Name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("sql/schema: missing primary key column %q", c.Name)
|
||||
}
|
||||
ct.PrimaryKey = append(ct.PrimaryKey, cc)
|
||||
}
|
||||
for j, idx := range t.Indexes {
|
||||
cidx := &Index{
|
||||
Name: idx.Name,
|
||||
Unique: idx.Unique,
|
||||
Columns: make([]*Column, len(idx.Columns)),
|
||||
}
|
||||
if at := idx.Annotation; at != nil {
|
||||
cat := *at
|
||||
cidx.Annotation = &cat
|
||||
}
|
||||
for k, c := range idx.Columns {
|
||||
cc, ok := ct.column(c.Name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("sql/schema: missing index column %q", c.Name)
|
||||
}
|
||||
cidx.Columns[k] = cc
|
||||
}
|
||||
ct.Indexes[j] = cidx
|
||||
}
|
||||
for j, fk := range t.ForeignKeys {
|
||||
cfk := &ForeignKey{
|
||||
Symbol: fk.Symbol,
|
||||
OnUpdate: fk.OnUpdate,
|
||||
OnDelete: fk.OnDelete,
|
||||
Columns: make([]*Column, len(fk.Columns)),
|
||||
RefColumns: make([]*Column, len(fk.RefColumns)),
|
||||
}
|
||||
for k, c := range fk.Columns {
|
||||
cc, ok := ct.column(c.Name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("sql/schema: missing foreign-key column %q", c.Name)
|
||||
}
|
||||
cfk.Columns[k] = cc
|
||||
}
|
||||
cref, ok := byName[fk.RefTable.Name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("sql/schema: missing foreign-key ref-table %q", fk.RefTable.Name)
|
||||
}
|
||||
cfk.RefTable = cref
|
||||
for k, c := range fk.RefColumns {
|
||||
cc, ok := cref.column(c.Name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("sql/schema: missing foreign-key ref-column %q", c.Name)
|
||||
}
|
||||
cfk.RefColumns[k] = cc
|
||||
}
|
||||
ct.ForeignKeys[j] = cfk
|
||||
}
|
||||
}
|
||||
return copyT, nil
|
||||
}
|
||||
|
||||
// Column schema definition for SQL dialects.
|
||||
type Column struct {
|
||||
Name string // column name.
|
||||
|
||||
@@ -7,6 +7,7 @@ package schema
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema/field"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -101,3 +102,50 @@ func TestColumn_ScanDefault(t *testing.T) {
|
||||
require.NoError(t, c1.ScanDefault("00000000-0000-0000-0000-000000000000"))
|
||||
require.Equal(t, "00000000-0000-0000-0000-000000000000", c1.Default)
|
||||
}
|
||||
|
||||
func TestCopyTables(t *testing.T) {
|
||||
users := &Table{
|
||||
Name: "users",
|
||||
Columns: []*Column{
|
||||
{Name: "id", Type: field.TypeInt},
|
||||
{Name: "name", Type: field.TypeString},
|
||||
{Name: "spouse_id", Type: field.TypeInt},
|
||||
},
|
||||
}
|
||||
users.PrimaryKey = users.Columns[:1]
|
||||
users.Indexes = append(users.Indexes, &Index{
|
||||
Name: "name",
|
||||
Columns: users.Columns[1:2],
|
||||
})
|
||||
users.AddForeignKey(&ForeignKey{
|
||||
Columns: users.Columns[2:],
|
||||
RefTable: users,
|
||||
RefColumns: users.Columns[:1],
|
||||
OnUpdate: SetNull,
|
||||
})
|
||||
users.SetAnnotation(&entsql.Annotation{Table: "Users"})
|
||||
pets := &Table{
|
||||
Name: "pets",
|
||||
Columns: []*Column{
|
||||
{Name: "id", Type: field.TypeInt},
|
||||
{Name: "name", Type: field.TypeString},
|
||||
{Name: "owner_id", Type: field.TypeInt},
|
||||
},
|
||||
}
|
||||
pets.Indexes = append(pets.Indexes, &Index{
|
||||
Name: "name",
|
||||
Unique: true,
|
||||
Columns: pets.Columns[1:2],
|
||||
Annotation: entsql.Desc(),
|
||||
})
|
||||
pets.AddForeignKey(&ForeignKey{
|
||||
Columns: pets.Columns[2:],
|
||||
RefTable: users,
|
||||
RefColumns: users.Columns[:1],
|
||||
OnDelete: SetDefault,
|
||||
})
|
||||
tables := []*Table{users, pets}
|
||||
copyT, err := CopyTables(tables)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tables, copyT)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user