mirror of
https://github.com/ent/ent.git
synced 2026-04-28 05:30:56 +03:00
dialect/entsql: allow to define auto increment start value (#4292)
Preparation to rewrite the universal id feature to rely on type ranges defined statically in the schema instead of dynamically in a database.
This commit is contained in:
@@ -126,6 +126,17 @@ type Annotation struct {
|
|||||||
//
|
//
|
||||||
Incremental *bool `json:"incremental,omitempty"`
|
Incremental *bool `json:"incremental,omitempty"`
|
||||||
|
|
||||||
|
// IncrementStart defines the auto-incremental start value of a column. For example:
|
||||||
|
//
|
||||||
|
// incrementStart := 100
|
||||||
|
// entsql.Annotation{
|
||||||
|
// IncrementStart: &incrementStart,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// By default, this value is nil defaulting to whatever the database settings are.
|
||||||
|
//
|
||||||
|
IncrementStart *int64 `json:"increment_start,omitempty"`
|
||||||
|
|
||||||
// OnDelete specifies a custom referential action for DELETE operations on parent
|
// OnDelete specifies a custom referential action for DELETE operations on parent
|
||||||
// table that has matching rows in the child table.
|
// table that has matching rows in the child table.
|
||||||
//
|
//
|
||||||
@@ -415,6 +426,9 @@ func (a Annotation) Merge(other schema.Annotation) schema.Annotation {
|
|||||||
if i := ant.Incremental; i != nil {
|
if i := ant.Incremental; i != nil {
|
||||||
a.Incremental = i
|
a.Incremental = i
|
||||||
}
|
}
|
||||||
|
if i := ant.IncrementStart; i != nil {
|
||||||
|
a.IncrementStart = i
|
||||||
|
}
|
||||||
if od := ant.OnDelete; od != "" {
|
if od := ant.OnDelete; od != "" {
|
||||||
a.OnDelete = od
|
a.OnDelete = od
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -896,12 +896,19 @@ func (a *Atlas) tables(tables []*Table) ([]*schema.Table, error) {
|
|||||||
at.SetComment(et.Comment)
|
at.SetComment(et.Comment)
|
||||||
}
|
}
|
||||||
a.sqlDialect.atTable(et, at)
|
a.sqlDialect.atTable(et, at)
|
||||||
if a.universalID && et.Name != TypeTable && len(et.PrimaryKey) == 1 {
|
// universalID is the old implementation of the global unique id, relying on a table in the database.
|
||||||
|
// The new implementation is based on annotations attached to the schema. Only one can be enabled.
|
||||||
|
switch {
|
||||||
|
case a.universalID && et.Annotation != nil && et.Annotation.IncrementStart != nil:
|
||||||
|
return nil, errors.New("sql/schema: universal id and increment start annotation are mutually exclusive")
|
||||||
|
case a.universalID && et.Name != TypeTable && len(et.PrimaryKey) == 1:
|
||||||
r, err := a.pkRange(et)
|
r, err := a.pkRange(et)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
a.sqlDialect.atIncrementT(at, r)
|
a.sqlDialect.atIncrementT(at, r)
|
||||||
|
case et.Annotation != nil && et.Annotation.IncrementStart != nil:
|
||||||
|
a.sqlDialect.atIncrementT(at, *et.Annotation.IncrementStart)
|
||||||
}
|
}
|
||||||
if err := a.aColumns(et, at); err != nil {
|
if err := a.aColumns(et, at); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -16,8 +16,10 @@ import (
|
|||||||
|
|
||||||
"ariga.io/atlas/sql/migrate"
|
"ariga.io/atlas/sql/migrate"
|
||||||
"ariga.io/atlas/sql/schema"
|
"ariga.io/atlas/sql/schema"
|
||||||
|
"ariga.io/atlas/sql/sqlite"
|
||||||
"ariga.io/atlas/sql/sqltool"
|
"ariga.io/atlas/sql/sqltool"
|
||||||
"entgo.io/ent/dialect"
|
"entgo.io/ent/dialect"
|
||||||
|
"entgo.io/ent/dialect/entsql"
|
||||||
"entgo.io/ent/dialect/sql"
|
"entgo.io/ent/dialect/sql"
|
||||||
"entgo.io/ent/schema/field"
|
"entgo.io/ent/schema/field"
|
||||||
|
|
||||||
@@ -416,18 +418,25 @@ func TestAtlas_StateReader(t *testing.T) {
|
|||||||
realm, err := m.StateReader(&Table{
|
realm, err := m.StateReader(&Table{
|
||||||
Name: "users",
|
Name: "users",
|
||||||
Columns: []*Column{
|
Columns: []*Column{
|
||||||
|
{Name: "id", Type: field.TypeInt64, Increment: true},
|
||||||
{Name: "name", Type: field.TypeString},
|
{Name: "name", Type: field.TypeString},
|
||||||
{Name: "active", Type: field.TypeBool},
|
{Name: "active", Type: field.TypeBool},
|
||||||
},
|
},
|
||||||
|
Annotation: &entsql.Annotation{
|
||||||
|
IncrementStart: func(i int64) *int64 { return &i }(100),
|
||||||
|
},
|
||||||
}).ReadState(context.Background())
|
}).ReadState(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, realm)
|
require.NotNil(t, realm)
|
||||||
require.Len(t, realm.Schemas, 1)
|
require.Len(t, realm.Schemas, 1)
|
||||||
require.Len(t, realm.Schemas[0].Tables, 1)
|
require.Len(t, realm.Schemas[0].Tables, 1)
|
||||||
require.Equal(t, realm.Schemas[0].Tables[0].Name, "users")
|
require.Equal(t, "users", realm.Schemas[0].Tables[0].Name)
|
||||||
|
require.Equal(t, []schema.Attr{&sqlite.AutoIncrement{Seq: 100}}, realm.Schemas[0].Tables[0].Attrs)
|
||||||
require.Equal(t,
|
require.Equal(t,
|
||||||
realm.Schemas[0].Tables[0].Columns,
|
realm.Schemas[0].Tables[0].Columns,
|
||||||
[]*schema.Column{
|
[]*schema.Column{
|
||||||
|
schema.NewIntColumn("id", "integer").
|
||||||
|
AddAttrs(&sqlite.AutoIncrement{}),
|
||||||
schema.NewStringColumn("name", "text"),
|
schema.NewStringColumn("name", "text"),
|
||||||
schema.NewBoolColumn("active", "bool"),
|
schema.NewBoolColumn("active", "bool"),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1612,7 +1612,7 @@ func (f Field) Column() *schema.Column {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// incremental returns if the column has an incremental behavior.
|
// incremental returns if the column has an incremental behavior.
|
||||||
// If no value is defined externally, we use a provided def flag
|
// If no value is defined externally, we use a provided def flag.
|
||||||
func (f Field) incremental(def bool) bool {
|
func (f Field) incremental(def bool) bool {
|
||||||
if ant := f.EntSQL(); ant != nil && ant.Incremental != nil {
|
if ant := f.EntSQL(); ant != nil && ant.Incremental != nil {
|
||||||
return *ant.Incremental
|
return *ant.Incremental
|
||||||
|
|||||||
Reference in New Issue
Block a user