mirror of
https://github.com/ent/ent.git
synced 2026-05-22 09:31:45 +03:00
schema/field: json type support (#38)
Summary: Pull Request resolved: https://github.com/facebookincubator/ent/pull/38 Only `IsNil` and `NotNil` predicates are supported this moment Reviewed By: alexsn Differential Revision: D17444976 fbshipit-source-id: 37336fa0bc7749af995933baee2e23bb7366dd78
This commit is contained in:
committed by
Facebook Github Bot
parent
83d0063437
commit
c3955a08f1
@@ -718,6 +718,11 @@ func (u *UpdateBuilder) Where(p *Predicate) *UpdateBuilder {
|
||||
return u
|
||||
}
|
||||
|
||||
// Empty reports whether this builder does not contain update changes.
|
||||
func (u *UpdateBuilder) Empty() bool {
|
||||
return len(u.columns) == 0 && len(u.nulls) == 0
|
||||
}
|
||||
|
||||
// Query returns query representation of an `UPDATE` statement.
|
||||
func (u *UpdateBuilder) Query() (string, []interface{}) {
|
||||
u.b.WriteString("UPDATE ")
|
||||
|
||||
@@ -54,17 +54,18 @@ func TestMySQL_Create(t *testing.T) {
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
{Name: "name", Type: field.TypeString, Nullable: true},
|
||||
{Name: "age", Type: field.TypeInt},
|
||||
{Name: "doc", Type: field.TypeJSON, Nullable: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
before: func(mock sqlmock.Sqlmock) {
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectQuery(escape("SHOW VARIABLES LIKE 'version'")).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("version", "5.7.23"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("version", "5.7.8"))
|
||||
mock.ExpectQuery(escape("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ?")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||
mock.ExpectExec(escape("CREATE TABLE IF NOT EXISTS `users`(`id` bigint AUTO_INCREMENT NOT NULL, `name` varchar(255) NULL, `age` bigint NOT NULL, PRIMARY KEY(`id`)) CHARACTER SET utf8mb4")).
|
||||
mock.ExpectExec(escape("CREATE TABLE IF NOT EXISTS `users`(`id` bigint AUTO_INCREMENT NOT NULL, `name` varchar(255) NULL, `age` bigint NOT NULL, `doc` json NULL, PRIMARY KEY(`id`)) CHARACTER SET utf8mb4")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
},
|
||||
@@ -81,6 +82,7 @@ func TestMySQL_Create(t *testing.T) {
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
{Name: "age", Type: field.TypeInt},
|
||||
{Name: "name", Type: field.TypeString, Unique: true},
|
||||
{Name: "doc", Type: field.TypeJSON, Nullable: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -91,7 +93,7 @@ func TestMySQL_Create(t *testing.T) {
|
||||
mock.ExpectQuery(escape("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ?")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||
mock.ExpectExec(escape("CREATE TABLE IF NOT EXISTS `users`(`id` bigint AUTO_INCREMENT NOT NULL, `age` bigint NOT NULL, `name` varchar(191) UNIQUE NOT NULL, PRIMARY KEY(`id`)) CHARACTER SET utf8mb4")).
|
||||
mock.ExpectExec(escape("CREATE TABLE IF NOT EXISTS `users`(`id` bigint AUTO_INCREMENT NOT NULL, `age` bigint NOT NULL, `name` varchar(191) UNIQUE NOT NULL, `doc` longblob NULL, PRIMARY KEY(`id`)) CHARACTER SET utf8mb4")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
},
|
||||
@@ -201,6 +203,7 @@ func TestMySQL_Create(t *testing.T) {
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
{Name: "name", Type: field.TypeString, Nullable: true},
|
||||
{Name: "age", Type: field.TypeInt, Default: 10},
|
||||
{Name: "doc", Type: field.TypeJSON, Nullable: true},
|
||||
},
|
||||
PrimaryKey: []*Column{
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
@@ -210,7 +213,7 @@ func TestMySQL_Create(t *testing.T) {
|
||||
before: func(mock sqlmock.Sqlmock) {
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectQuery(escape("SHOW VARIABLES LIKE 'version'")).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("version", "5.7.23"))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("version", "5.6.0"))
|
||||
mock.ExpectQuery(escape("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ?")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
@@ -218,7 +221,8 @@ func TestMySQL_Create(t *testing.T) {
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"column_name", "column_type", "is_nullable", "column_key", "column_default", "extra", "character_set_name", "collation_name"}).
|
||||
AddRow("id", "bigint(20)", "NO", "PRI", "NULL", "auto_increment", "", "").
|
||||
AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", ""))
|
||||
AddRow("name", "varchar(255)", "NO", "YES", "NULL", "", "", "").
|
||||
AddRow("doc", "longblob", "NO", "YES", "NULL", "", "", ""))
|
||||
mock.ExpectQuery(escape("SELECT `index_name`, `column_name`, `non_unique`, `seq_in_index` FROM INFORMATION_SCHEMA.STATISTICS WHERE `TABLE_SCHEMA` = (SELECT DATABASE()) AND `TABLE_NAME` = ?")).
|
||||
WithArgs("users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"index_name", "column_name", "non_unique", "seq_in_index"}).
|
||||
|
||||
@@ -253,6 +253,11 @@ func (c *Column) MySQLType(version string) (t string) {
|
||||
case size <= math.MaxUint32:
|
||||
t = "longblob"
|
||||
}
|
||||
case field.TypeJSON:
|
||||
t = "json"
|
||||
if compareVersions(version, "5.7.8") == -1 {
|
||||
t = "longblob"
|
||||
}
|
||||
case field.TypeString:
|
||||
size := c.Size
|
||||
if size == 0 {
|
||||
@@ -298,6 +303,8 @@ func (c *Column) SQLiteType() (t string) {
|
||||
t = "real"
|
||||
case field.TypeTime:
|
||||
t = "datetime"
|
||||
case field.TypeJSON:
|
||||
t = "json"
|
||||
default:
|
||||
panic("unsupported type " + c.Type.String())
|
||||
}
|
||||
@@ -371,6 +378,8 @@ func (c *Column) ScanMySQL(rows *sql.Rows) error {
|
||||
case "longtext":
|
||||
c.Size = math.MaxInt32
|
||||
c.Type = field.TypeString
|
||||
case "json":
|
||||
c.Type = field.TypeJSON
|
||||
}
|
||||
if defaults.Valid && defaults.String != Null {
|
||||
return c.ScanDefault(defaults.String)
|
||||
@@ -504,12 +513,9 @@ func (c *Column) nullable(b *sql.ColumnBuilder) {
|
||||
// prefix key limit (767).
|
||||
func (c *Column) defaultSize(version string) int {
|
||||
size := DefaultStringLen
|
||||
parts := strings.Split(version, ".")
|
||||
switch {
|
||||
// invalid version.
|
||||
case len(parts) == 1 || parts[0] == "" || parts[1] == "":
|
||||
// version is > 5.6.*.
|
||||
case parts[0] > "5" || parts[1] > "6":
|
||||
// version is >= 5.7.
|
||||
case compareVersions(version, "5.7.0") != -1:
|
||||
// non-unique, or not part of any index (reaching the error 1071).
|
||||
case !c.Unique && len(c.indexes) == 0:
|
||||
default:
|
||||
@@ -643,3 +649,63 @@ func (i *Indexes) ScanMySQL(rows *sql.Rows) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// compareVersions returns an integer comparing the 2 versions.
|
||||
func compareVersions(v1, v2 string) int {
|
||||
pv1, ok1 := parseVersion(v1)
|
||||
pv2, ok2 := parseVersion(v2)
|
||||
if !ok1 && !ok2 {
|
||||
return 0
|
||||
}
|
||||
if !ok1 {
|
||||
return -1
|
||||
}
|
||||
if !ok2 {
|
||||
return 1
|
||||
}
|
||||
if v := compare(pv1.major, pv2.major); v != 0 {
|
||||
return v
|
||||
}
|
||||
if v := compare(pv1.minor, pv2.minor); v != 0 {
|
||||
return v
|
||||
}
|
||||
return compare(pv1.patch, pv2.patch)
|
||||
}
|
||||
|
||||
// version represents a parsed MySQL version.
|
||||
type version struct {
|
||||
major int
|
||||
minor int
|
||||
patch int
|
||||
}
|
||||
|
||||
// parseVersion returns an integer comparing the 2 versions.
|
||||
func parseVersion(v string) (*version, bool) {
|
||||
parts := strings.Split(v, ".")
|
||||
if len(parts) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
var (
|
||||
err error
|
||||
ver = &version{}
|
||||
)
|
||||
for i, e := range []*int{&ver.major, &ver.minor, &ver.patch} {
|
||||
if i == len(parts) {
|
||||
break
|
||||
}
|
||||
if *e, err = strconv.Atoi(parts[i]); err != nil {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return ver, true
|
||||
}
|
||||
|
||||
func compare(v1, v2 int) int {
|
||||
if v1 == v2 {
|
||||
return 0
|
||||
}
|
||||
if v1 < v2 {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ func TestSQLite_Create(t *testing.T) {
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
{Name: "name", Type: field.TypeString, Nullable: true},
|
||||
{Name: "age", Type: field.TypeInt},
|
||||
{Name: "doc", Type: field.TypeJSON, Nullable: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -71,7 +72,7 @@ func TestSQLite_Create(t *testing.T) {
|
||||
mock.ExpectQuery(escape("SELECT COUNT(*) FROM `sqlite_master` WHERE `type` = ? AND `name` = ?")).
|
||||
WithArgs("table", "users").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||
mock.ExpectExec(escape("CREATE TABLE `users`(`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `name` varchar(255) NULL, `age` integer NOT NULL)")).
|
||||
mock.ExpectExec(escape("CREATE TABLE `users`(`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `name` varchar(255) NULL, `age` integer NOT NULL, `doc` json NULL)")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user