entc/integration/migrate: enable postgres 10,11 in migrate test

Summary: Pull Request resolved: https://github.com/facebookincubator/ent/pull/132

Reviewed By: alexsn

Differential Revision: D18203398

fbshipit-source-id: a261ed3934d2e4262d7177b41546b2239e798ef5
This commit is contained in:
Ariel Mashraki
2019-10-29 10:15:01 -07:00
committed by Facebook Github Bot
parent 440a737d73
commit 38fcf995d0
7 changed files with 133 additions and 34 deletions

View File

@@ -41,8 +41,8 @@ var (
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "age", Type: field.TypeInt},
{Name: "name", Type: field.TypeString, Size: 2147483647},
{Name: "phone", Type: field.TypeString},
{Name: "buffer", Type: field.TypeBytes, Default: user.DefaultBuffer},
{Name: "phone", Type: field.TypeString, Default: user.DefaultPhone},
{Name: "buffer", Type: field.TypeBytes, Nullable: true},
{Name: "title", Type: field.TypeString, Default: user.DefaultTitle},
{Name: "renamed", Type: field.TypeString, Nullable: true},
{Name: "blob", Type: field.TypeBytes, Nullable: true, Size: 1000},

View File

@@ -22,10 +22,11 @@ func (User) Fields() []ent.Field {
field.Int("age"),
// extending name field to longtext.
field.Text("name"),
// adding new columns.
field.String("phone"),
// adding new columns (must be either optional, or with a default value).
field.String("phone").
Default("unknown"),
field.Bytes("buffer").
Default([]byte("{}")),
Optional(),
// adding new column with supported default value
// in the database side, will append this value to
// all existing rows.

View File

@@ -54,10 +54,10 @@ var Columns = []string{
var (
fields = schema.User{}.Fields()
// descBuffer is the schema descriptor for buffer field.
descBuffer = fields[3].Descriptor()
// DefaultBuffer holds the default value on creation for the buffer field.
DefaultBuffer = descBuffer.Default.([]byte)
// descPhone is the schema descriptor for phone field.
descPhone = fields[2].Descriptor()
// DefaultPhone holds the default value on creation for the phone field.
DefaultPhone = descPhone.Default.(string)
// descTitle is the schema descriptor for title field.
descTitle = fields[4].Descriptor()

View File

@@ -633,6 +633,24 @@ func BufferLTE(v []byte) predicate.User {
)
}
// BufferIsNil applies the IsNil predicate on the "buffer" field.
func BufferIsNil() predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.IsNull(s.C(FieldBuffer)))
},
)
}
// BufferNotNil applies the NotNil predicate on the "buffer" field.
func BufferNotNil() predicate.User {
return predicate.User(
func(s *sql.Selector) {
s.Where(sql.NotNull(s.C(FieldBuffer)))
},
)
}
// TitleEQ applies the EQ predicate on the "title" field.
func TitleEQ(v string) predicate.User {
return predicate.User(

View File

@@ -46,6 +46,14 @@ func (uc *UserCreate) SetPhone(s string) *UserCreate {
return uc
}
// SetNillablePhone sets the phone field if the given value is not nil.
func (uc *UserCreate) SetNillablePhone(s *string) *UserCreate {
if s != nil {
uc.SetPhone(*s)
}
return uc
}
// SetBuffer sets the buffer field.
func (uc *UserCreate) SetBuffer(b []byte) *UserCreate {
uc.buffer = &b
@@ -109,11 +117,8 @@ func (uc *UserCreate) Save(ctx context.Context) (*User, error) {
return nil, errors.New("entv2: missing required field \"name\"")
}
if uc.phone == nil {
return nil, errors.New("entv2: missing required field \"phone\"")
}
if uc.buffer == nil {
v := user.DefaultBuffer
uc.buffer = &v
v := user.DefaultPhone
uc.phone = &v
}
if uc.title == nil {
v := user.DefaultTitle

View File

@@ -23,6 +23,7 @@ type UserUpdate struct {
name *string
phone *string
buffer *[]byte
clearbuffer bool
title *string
new_name *string
clearnew_name bool
@@ -68,12 +69,27 @@ func (uu *UserUpdate) SetPhone(s string) *UserUpdate {
return uu
}
// SetNillablePhone sets the phone field if the given value is not nil.
func (uu *UserUpdate) SetNillablePhone(s *string) *UserUpdate {
if s != nil {
uu.SetPhone(*s)
}
return uu
}
// SetBuffer sets the buffer field.
func (uu *UserUpdate) SetBuffer(b []byte) *UserUpdate {
uu.buffer = &b
return uu
}
// ClearBuffer clears the value of buffer.
func (uu *UserUpdate) ClearBuffer() *UserUpdate {
uu.buffer = nil
uu.clearbuffer = true
return uu
}
// SetTitle sets the title field.
func (uu *UserUpdate) SetTitle(s string) *UserUpdate {
uu.title = &s
@@ -224,6 +240,9 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
if value := uu.buffer; value != nil {
updater.Set(user.FieldBuffer, *value)
}
if uu.clearbuffer {
updater.SetNull(user.FieldBuffer)
}
if value := uu.title; value != nil {
updater.Set(user.FieldTitle, *value)
}
@@ -266,6 +285,7 @@ type UserUpdateOne struct {
name *string
phone *string
buffer *[]byte
clearbuffer bool
title *string
new_name *string
clearnew_name bool
@@ -304,12 +324,27 @@ func (uuo *UserUpdateOne) SetPhone(s string) *UserUpdateOne {
return uuo
}
// SetNillablePhone sets the phone field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillablePhone(s *string) *UserUpdateOne {
if s != nil {
uuo.SetPhone(*s)
}
return uuo
}
// SetBuffer sets the buffer field.
func (uuo *UserUpdateOne) SetBuffer(b []byte) *UserUpdateOne {
uuo.buffer = &b
return uuo
}
// ClearBuffer clears the value of buffer.
func (uuo *UserUpdateOne) ClearBuffer() *UserUpdateOne {
uuo.buffer = nil
uuo.clearbuffer = true
return uuo
}
// SetTitle sets the title field.
func (uuo *UserUpdateOne) SetTitle(s string) *UserUpdateOne {
uuo.title = &s
@@ -468,6 +503,11 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) {
updater.Set(user.FieldBuffer, *value)
u.Buffer = *value
}
if uuo.clearbuffer {
var value []byte
u.Buffer = value
updater.SetNull(user.FieldBuffer)
}
if value := uuo.title; value != nil {
updater.Set(user.FieldTitle, *value)
u.Title = *value

View File

@@ -7,8 +7,10 @@ package migrate
import (
"context"
"fmt"
"strings"
"testing"
"github.com/facebookincubator/ent/dialect"
"github.com/facebookincubator/ent/dialect/sql"
"github.com/facebookincubator/ent/entc/integration/migrate/entv1"
migratev1 "github.com/facebookincubator/ent/entc/integration/migrate/entv1/migrate"
@@ -16,7 +18,9 @@ import (
"github.com/facebookincubator/ent/entc/integration/migrate/entv2"
migratev2 "github.com/facebookincubator/ent/entc/integration/migrate/entv2/migrate"
"github.com/facebookincubator/ent/entc/integration/migrate/entv2/user"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
"github.com/stretchr/testify/require"
)
@@ -35,29 +39,34 @@ func TestMySQL(t *testing.T) {
drv, err := sql.Open("mysql", fmt.Sprintf("root:pass@tcp(localhost:%d)/migrate?parseTime=True", port))
require.NoError(t, err, "connecting to migrate database")
// run migration and execute queries on v1.
clientv1 := entv1.NewClient(entv1.Driver(drv))
require.NoError(t, clientv1.Schema.Create(ctx, migratev1.WithGlobalUniqueID(true)))
SanityV1(t, clientv1)
// run migration and execute queries on v2.
clientv2 := entv2.NewClient(entv2.Driver(drv))
require.NoError(t, clientv2.Schema.Create(ctx, migratev2.WithGlobalUniqueID(true), migratev2.WithDropIndex(true), migratev2.WithDropColumn(true)))
SanityV2(t, clientv2)
V1ToV2(t, clientv1, clientv2)
})
}
}
// since "users" created in the migration of v1, it will occupy the range of 0 ... 1<<32-1,
// even though they are ordered differently in the migration of v2 (groups, pets, users).
idRange(t, clientv2.User.Create().SetAge(1).SetName("foo").SetPhone("phone").SaveX(ctx).ID, 0, 1<<32)
idRange(t, clientv2.Group.Create().SaveX(ctx).ID, 1<<32-1, 2<<32)
idRange(t, clientv2.Pet.Create().SaveX(ctx).ID, 2<<32-1, 3<<32)
func TestPostgres(t *testing.T) {
// Version 12 is disabled here due to segfault on migration. It will be re-enabled on its next release.
// More info can be found here: https://www.postgresql.org/message-id/23031.1572362774%40sss.pgh.pa.us
for version, port := range map[string]int{"10": 5430, "11": 5431} {
t.Run(version, func(t *testing.T) {
dsn := fmt.Sprintf("host=localhost port=%d user=postgres password=pass sslmode=disable", port)
root, err := sql.Open(dialect.Postgres, dsn)
require.NoError(t, err)
defer root.Close()
ctx := context.Background()
err = root.Exec(ctx, "CREATE DATABASE migrate", []interface{}{}, new(sql.Result))
require.NoError(t, err, "creating database")
defer root.Exec(ctx, "DROP DATABASE migrate", []interface{}{}, new(sql.Result))
// sql specific predicates.
EqualFold(t, clientv2)
ContainsFold(t, clientv2)
drv, err := sql.Open(dialect.Postgres, dsn+" dbname=migrate")
require.NoError(t, err, "connecting to migrate database")
defer drv.Close()
// "renamed" field was renamed to "new_name".
exist := clientv2.User.Query().Where(user.NewName("renamed")).ExistX(ctx)
require.True(t, exist, "expect renamed column to have previous values")
clientv1 := entv1.NewClient(entv1.Driver(drv))
clientv2 := entv2.NewClient(entv2.Driver(drv))
V1ToV2(t, clientv1, clientv2)
})
}
}
@@ -84,6 +93,32 @@ func TestSQLite(t *testing.T) {
ContainsFold(t, client)
}
func V1ToV2(t *testing.T, clientv1 *entv1.Client, clientv2 *entv2.Client) {
ctx := context.Background()
// run migration and execute queries on v1.
require.NoError(t, clientv1.Schema.Create(ctx, migratev1.WithGlobalUniqueID(true)))
SanityV1(t, clientv1)
// run migration and execute queries on v2.
require.NoError(t, clientv2.Schema.Create(ctx, migratev2.WithGlobalUniqueID(true), migratev2.WithDropIndex(true), migratev2.WithDropColumn(true)))
SanityV2(t, clientv2)
// since "users" created in the migration of v1, it will occupy the range of 0 ... 1<<32-1,
// even though they are ordered differently in the migration of v2 (groups, pets, users).
idRange(t, clientv2.User.Create().SetAge(1).SetName("foo").SetPhone("phone").SaveX(ctx).ID, 0, 1<<32)
idRange(t, clientv2.Group.Create().SaveX(ctx).ID, 1<<32-1, 2<<32)
idRange(t, clientv2.Pet.Create().SaveX(ctx).ID, 2<<32-1, 3<<32)
// sql specific predicates.
EqualFold(t, clientv2)
ContainsFold(t, clientv2)
// "renamed" field was renamed to "new_name".
exist := clientv2.User.Query().Where(user.NewName("renamed")).ExistX(ctx)
require.True(t, exist, "expect renamed column to have previous values")
}
func SanityV1(t *testing.T, client *entv1.Client) {
ctx := context.Background()
u := client.User.Create().SetAge(1).SetName("foo").SetRenamed("renamed").SaveX(ctx)
@@ -102,7 +137,7 @@ func SanityV1(t *testing.T, client *entv1.Client) {
u = u.Update().SetBlob([]byte("hello")).SaveX(ctx)
require.Equal(t, "hello", string(u.Blob))
_, err = u.Update().SetBlob(make([]byte, 256)).Save(ctx)
require.Error(t, err, "data too long for column 'blob' error")
require.True(t, strings.Contains(t.Name(), "Postgres") || err != nil, "blob should be limited on SQLite and MySQL")
// invalid enum value.
_, err = client.User.Create().SetAge(1).SetName("bar").SetState("unknown").Save(ctx)
@@ -111,7 +146,7 @@ func SanityV1(t *testing.T, client *entv1.Client) {
func SanityV2(t *testing.T, client *entv2.Client) {
ctx := context.Background()
u := client.User.Create().SetAge(1).SetName("bar").SetPhone("100").SetState(user.StateLoggedOut).SaveX(ctx)
u := client.User.Create().SetAge(1).SetName("bar").SetPhone("100").SetBuffer([]byte("{}")).SetState(user.StateLoggedOut).SaveX(ctx)
require.Equal(t, 1, u.Age)
require.Equal(t, "bar", u.Name)
require.Equal(t, []byte("{}"), u.Buffer)