mirror of
https://github.com/ent/ent.git
synced 2026-05-04 08:30:57 +03:00
dialect/entsql: add support for column default using annotation
Fixed #1033
This commit is contained in:
committed by
Ariel Mashraki
parent
3db3f5fd1a
commit
745afde770
@@ -58,7 +58,7 @@ func TestMySQL_Create(t *testing.T) {
|
||||
{Name: "doc", Type: field.TypeJSON, Nullable: true},
|
||||
{Name: "enums", Type: field.TypeEnum, Enums: []string{"a", "b"}},
|
||||
{Name: "uuid", Type: field.TypeUUID, Nullable: true},
|
||||
{Name: "datetime", Type: field.TypeTime, SchemaType: map[string]string{dialect.MySQL: "datetime"}, Nullable: true},
|
||||
{Name: "datetime", Type: field.TypeTime, SchemaType: map[string]string{dialect.MySQL: "datetime"}, Default: "CURRENT_TIMESTAMP"},
|
||||
{Name: "decimal", Type: field.TypeFloat32, SchemaType: map[string]string{dialect.MySQL: "decimal(6,2)"}},
|
||||
},
|
||||
Annotation: &entsql.Annotation{
|
||||
@@ -71,7 +71,7 @@ func TestMySQL_Create(t *testing.T) {
|
||||
before: func(mock mysqlMock) {
|
||||
mock.start("5.7.8")
|
||||
mock.tableExists("users", false)
|
||||
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, `enums` enum('a', 'b') NOT NULL, `uuid` char(36) binary NULL, `datetime` datetime NULL, `decimal` decimal(6,2) NOT NULL, PRIMARY KEY(`id`)) CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = INNODB")).
|
||||
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, `enums` enum('a', 'b') NOT NULL, `uuid` char(36) binary NULL, `datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `decimal` decimal(6,2) NOT NULL, PRIMARY KEY(`id`)) CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = INNODB")).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
},
|
||||
@@ -219,7 +219,7 @@ func TestMySQL_Create(t *testing.T) {
|
||||
{Name: "big", Type: field.TypeInt64},
|
||||
{Name: "big_unsigned", Type: field.TypeUint64},
|
||||
{Name: "decimal", Type: field.TypeFloat64, SchemaType: map[string]string{dialect.MySQL: "decimal(6,2)"}},
|
||||
{Name: "timestamp", Type: field.TypeTime, SchemaType: map[string]string{dialect.MySQL: "TIMESTAMP"}},
|
||||
{Name: "timestamp", Type: field.TypeTime, SchemaType: map[string]string{dialect.MySQL: "TIMESTAMP"}, Default: "CURRENT_TIMESTAMP"},
|
||||
},
|
||||
PrimaryKey: []*Column{
|
||||
{Name: "id", Type: field.TypeInt, Increment: true},
|
||||
|
||||
@@ -62,7 +62,7 @@ func TestPostgres_Create(t *testing.T) {
|
||||
{Name: "age", Type: field.TypeInt},
|
||||
{Name: "doc", Type: field.TypeJSON, Nullable: true},
|
||||
{Name: "enums", Type: field.TypeEnum, Enums: []string{"a", "b"}, Default: "a"},
|
||||
{Name: "uuid", Type: field.TypeUUID},
|
||||
{Name: "uuid", Type: field.TypeUUID, Default: "uuid_generate_v4()"},
|
||||
{Name: "price", Type: field.TypeFloat64, SchemaType: map[string]string{dialect.Postgres: "numeric(5,2)"}},
|
||||
},
|
||||
},
|
||||
@@ -70,7 +70,7 @@ func TestPostgres_Create(t *testing.T) {
|
||||
before: func(mock pgMock) {
|
||||
mock.start("120000")
|
||||
mock.tableExists("users", false)
|
||||
mock.ExpectExec(escape(`CREATE TABLE IF NOT EXISTS "users"("id" bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, "name" varchar NULL, "age" bigint NOT NULL, "doc" jsonb NULL, "enums" varchar NOT NULL DEFAULT 'a', "uuid" uuid NOT NULL, "price" numeric(5,2) NOT NULL, PRIMARY KEY("id"))`)).
|
||||
mock.ExpectExec(escape(`CREATE TABLE IF NOT EXISTS "users"("id" bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, "name" varchar NULL, "age" bigint NOT NULL, "doc" jsonb NULL, "enums" varchar NOT NULL DEFAULT 'a', "uuid" uuid NOT NULL DEFAULT uuid_generate_v4(), "price" numeric(5,2) NOT NULL, PRIMARY KEY("id"))`)).
|
||||
WillReturnResult(sqlmock.NewResult(0, 1))
|
||||
mock.ExpectCommit()
|
||||
},
|
||||
@@ -241,7 +241,7 @@ func TestPostgres_Create(t *testing.T) {
|
||||
{Name: "uuid", Type: field.TypeUUID, Nullable: true},
|
||||
{Name: "text", Type: field.TypeString, Nullable: true, Size: math.MaxInt32},
|
||||
{Name: "age", Type: field.TypeInt},
|
||||
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{dialect.Postgres: "date"}},
|
||||
{Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{dialect.Postgres: "date"}, Default: "CURRENT_DATE"},
|
||||
{Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{dialect.MySQL: "date"}, Nullable: true},
|
||||
{Name: "deleted_at", Type: field.TypeTime, Nullable: true},
|
||||
{Name: "cidr", Type: field.TypeString, SchemaType: map[string]string{dialect.Postgres: "cidr"}},
|
||||
|
||||
@@ -271,31 +271,32 @@ func (c *Column) ScanDefault(value string) error {
|
||||
// Note that, in SQLite if a NOT NULL constraint is specified,
|
||||
// then the column must have a default value which not NULL.
|
||||
func (c *Column) defaultValue(b *sql.ColumnBuilder) {
|
||||
// has default, and it's supported in the database level.
|
||||
if c.Default != nil && c.supportDefault() {
|
||||
attr := "DEFAULT "
|
||||
switch v := c.Default.(type) {
|
||||
case bool:
|
||||
attr += strconv.FormatBool(v)
|
||||
case string:
|
||||
// Escape single quote by replacing each with 2.
|
||||
attr += fmt.Sprintf("'%s'", strings.ReplaceAll(v, "'", "''"))
|
||||
default:
|
||||
attr += fmt.Sprint(v)
|
||||
}
|
||||
b.Attr(attr)
|
||||
if c.Default == nil || !c.supportDefault() {
|
||||
return
|
||||
}
|
||||
// Has default and the database supports adding this default.
|
||||
attr := fmt.Sprint(c.Default)
|
||||
switch v := c.Default.(type) {
|
||||
case bool:
|
||||
attr = strconv.FormatBool(v)
|
||||
case string:
|
||||
if t := c.Type; t != field.TypeUUID && t != field.TypeTime {
|
||||
// Escape single quote by replacing each with 2.
|
||||
attr = fmt.Sprintf("'%s'", strings.ReplaceAll(v, "'", "''"))
|
||||
}
|
||||
}
|
||||
b.Attr("DEFAULT " + attr)
|
||||
}
|
||||
|
||||
// supportDefault reports if the column type supports default value.
|
||||
func (c Column) supportDefault() bool {
|
||||
switch {
|
||||
case c.Type == field.TypeString || c.Type == field.TypeEnum:
|
||||
switch t := c.Type; t {
|
||||
case field.TypeString, field.TypeEnum:
|
||||
return c.Size < 1<<16 // not a text.
|
||||
case c.Type.Numeric(), c.Type == field.TypeBool:
|
||||
case field.TypeBool, field.TypeTime, field.TypeUUID:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
return t.Numeric()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user