diff --git a/entc/integration/ent/entql.go b/entc/integration/ent/entql.go index 4e25a9007..c04019fa0 100644 --- a/entc/integration/ent/entql.go +++ b/entc/integration/ent/entql.go @@ -110,6 +110,7 @@ var schemaGraph = func() *sqlgraph.Schema { Type: "ExValueScan", Fields: map[string]*sqlgraph.FieldSpec{ exvaluescan.FieldBinary: {Type: field.TypeString, Column: exvaluescan.FieldBinary}, + exvaluescan.FieldBinaryBytes: {Type: field.TypeBytes, Column: exvaluescan.FieldBinaryBytes}, exvaluescan.FieldBinaryOptional: {Type: field.TypeString, Column: exvaluescan.FieldBinaryOptional}, exvaluescan.FieldText: {Type: field.TypeString, Column: exvaluescan.FieldText}, exvaluescan.FieldTextOptional: {Type: field.TypeString, Column: exvaluescan.FieldTextOptional}, @@ -1030,6 +1031,11 @@ func (f *ExValueScanFilter) WhereBinary(p entql.StringP) { f.Where(p.Field(exvaluescan.FieldBinary)) } +// WhereBinaryBytes applies the entql []byte predicate on the binary_bytes field. +func (f *ExValueScanFilter) WhereBinaryBytes(p entql.BytesP) { + f.Where(p.Field(exvaluescan.FieldBinaryBytes)) +} + // WhereBinaryOptional applies the entql string predicate on the binary_optional field. func (f *ExValueScanFilter) WhereBinaryOptional(p entql.StringP) { f.Where(p.Field(exvaluescan.FieldBinaryOptional)) diff --git a/entc/integration/ent/exvaluescan.go b/entc/integration/ent/exvaluescan.go index 09b8d574c..c8917caf5 100644 --- a/entc/integration/ent/exvaluescan.go +++ b/entc/integration/ent/exvaluescan.go @@ -24,6 +24,8 @@ type ExValueScan struct { ID int `json:"id,omitempty"` // Binary holds the value of the "binary" field. Binary *url.URL `json:"binary,omitempty"` + // BinaryBytes holds the value of the "binary_bytes" field. + BinaryBytes *url.URL `json:"binary_bytes,omitempty"` // BinaryOptional holds the value of the "binary_optional" field. BinaryOptional *url.URL `json:"binary_optional,omitempty"` // Text holds the value of the "text" field. @@ -48,6 +50,8 @@ func (*ExValueScan) scanValues(columns []string) ([]any, error) { values[i] = new(sql.NullInt64) case exvaluescan.FieldBinary: values[i] = exvaluescan.ValueScanner.Binary.ScanValue() + case exvaluescan.FieldBinaryBytes: + values[i] = exvaluescan.ValueScanner.BinaryBytes.ScanValue() case exvaluescan.FieldBinaryOptional: values[i] = exvaluescan.ValueScanner.BinaryOptional.ScanValue() case exvaluescan.FieldText: @@ -87,6 +91,12 @@ func (evs *ExValueScan) assignValues(columns []string, values []any) error { } else { evs.Binary = value } + case exvaluescan.FieldBinaryBytes: + if value, err := exvaluescan.ValueScanner.BinaryBytes.FromValue(values[i]); err != nil { + return err + } else { + evs.BinaryBytes = value + } case exvaluescan.FieldBinaryOptional: if value, err := exvaluescan.ValueScanner.BinaryOptional.FromValue(values[i]); err != nil { return err @@ -162,6 +172,9 @@ func (evs *ExValueScan) String() string { builder.WriteString("binary=") builder.WriteString(fmt.Sprintf("%v", evs.Binary)) builder.WriteString(", ") + builder.WriteString("binary_bytes=") + builder.WriteString(fmt.Sprintf("%v", evs.BinaryBytes)) + builder.WriteString(", ") builder.WriteString("binary_optional=") builder.WriteString(fmt.Sprintf("%v", evs.BinaryOptional)) builder.WriteString(", ") diff --git a/entc/integration/ent/exvaluescan/exvaluescan.go b/entc/integration/ent/exvaluescan/exvaluescan.go index 4c84dc9e1..77a83dfa5 100644 --- a/entc/integration/ent/exvaluescan/exvaluescan.go +++ b/entc/integration/ent/exvaluescan/exvaluescan.go @@ -21,6 +21,8 @@ const ( FieldID = "id" // FieldBinary holds the string denoting the binary field in the database. FieldBinary = "binary" + // FieldBinaryBytes holds the string denoting the binary_bytes field in the database. + FieldBinaryBytes = "binary_bytes" // FieldBinaryOptional holds the string denoting the binary_optional field in the database. FieldBinaryOptional = "binary_optional" // FieldText holds the string denoting the text field in the database. @@ -41,6 +43,7 @@ const ( var Columns = []string{ FieldID, FieldBinary, + FieldBinaryBytes, FieldBinaryOptional, FieldText, FieldTextOptional, @@ -63,6 +66,7 @@ var ( // ValueScanner of all ExValueScan fields. ValueScanner struct { Binary field.TypeValueScanner[*url.URL] + BinaryBytes field.TypeValueScanner[*url.URL] BinaryOptional field.TypeValueScanner[*url.URL] Text field.TypeValueScanner[*big.Int] TextOptional field.TypeValueScanner[*big.Int] diff --git a/entc/integration/ent/exvaluescan_create.go b/entc/integration/ent/exvaluescan_create.go index 0d7855570..c49dfa911 100644 --- a/entc/integration/ent/exvaluescan_create.go +++ b/entc/integration/ent/exvaluescan_create.go @@ -33,6 +33,12 @@ func (evsc *ExValueScanCreate) SetBinary(u *url.URL) *ExValueScanCreate { return evsc } +// SetBinaryBytes sets the "binary_bytes" field. +func (evsc *ExValueScanCreate) SetBinaryBytes(u *url.URL) *ExValueScanCreate { + evsc.mutation.SetBinaryBytes(u) + return evsc +} + // SetBinaryOptional sets the "binary_optional" field. func (evsc *ExValueScanCreate) SetBinaryOptional(u *url.URL) *ExValueScanCreate { evsc.mutation.SetBinaryOptional(u) @@ -114,6 +120,9 @@ func (evsc *ExValueScanCreate) check() error { if _, ok := evsc.mutation.Binary(); !ok { return &ValidationError{Name: "binary", err: errors.New(`ent: missing required field "ExValueScan.binary"`)} } + if _, ok := evsc.mutation.BinaryBytes(); !ok { + return &ValidationError{Name: "binary_bytes", err: errors.New(`ent: missing required field "ExValueScan.binary_bytes"`)} + } if _, ok := evsc.mutation.Text(); !ok { return &ValidationError{Name: "text", err: errors.New(`ent: missing required field "ExValueScan.text"`)} } @@ -161,6 +170,14 @@ func (evsc *ExValueScanCreate) createSpec() (*ExValueScan, *sqlgraph.CreateSpec, _spec.SetField(exvaluescan.FieldBinary, field.TypeString, vv) _node.Binary = value } + if value, ok := evsc.mutation.BinaryBytes(); ok { + vv, err := exvaluescan.ValueScanner.BinaryBytes.Value(value) + if err != nil { + return nil, nil, err + } + _spec.SetField(exvaluescan.FieldBinaryBytes, field.TypeBytes, vv) + _node.BinaryBytes = value + } if value, ok := evsc.mutation.BinaryOptional(); ok { vv, err := exvaluescan.ValueScanner.BinaryOptional.Value(value) if err != nil { @@ -273,6 +290,18 @@ func (u *ExValueScanUpsert) UpdateBinary() *ExValueScanUpsert { return u } +// SetBinaryBytes sets the "binary_bytes" field. +func (u *ExValueScanUpsert) SetBinaryBytes(v *url.URL) *ExValueScanUpsert { + u.Set(exvaluescan.FieldBinaryBytes, v) + return u +} + +// UpdateBinaryBytes sets the "binary_bytes" field to the value that was provided on create. +func (u *ExValueScanUpsert) UpdateBinaryBytes() *ExValueScanUpsert { + u.SetExcluded(exvaluescan.FieldBinaryBytes) + return u +} + // SetBinaryOptional sets the "binary_optional" field. func (u *ExValueScanUpsert) SetBinaryOptional(v *url.URL) *ExValueScanUpsert { u.Set(exvaluescan.FieldBinaryOptional, v) @@ -417,6 +446,20 @@ func (u *ExValueScanUpsertOne) UpdateBinary() *ExValueScanUpsertOne { }) } +// SetBinaryBytes sets the "binary_bytes" field. +func (u *ExValueScanUpsertOne) SetBinaryBytes(v *url.URL) *ExValueScanUpsertOne { + return u.Update(func(s *ExValueScanUpsert) { + s.SetBinaryBytes(v) + }) +} + +// UpdateBinaryBytes sets the "binary_bytes" field to the value that was provided on create. +func (u *ExValueScanUpsertOne) UpdateBinaryBytes() *ExValueScanUpsertOne { + return u.Update(func(s *ExValueScanUpsert) { + s.UpdateBinaryBytes() + }) +} + // SetBinaryOptional sets the "binary_optional" field. func (u *ExValueScanUpsertOne) SetBinaryOptional(v *url.URL) *ExValueScanUpsertOne { return u.Update(func(s *ExValueScanUpsert) { @@ -742,6 +785,20 @@ func (u *ExValueScanUpsertBulk) UpdateBinary() *ExValueScanUpsertBulk { }) } +// SetBinaryBytes sets the "binary_bytes" field. +func (u *ExValueScanUpsertBulk) SetBinaryBytes(v *url.URL) *ExValueScanUpsertBulk { + return u.Update(func(s *ExValueScanUpsert) { + s.SetBinaryBytes(v) + }) +} + +// UpdateBinaryBytes sets the "binary_bytes" field to the value that was provided on create. +func (u *ExValueScanUpsertBulk) UpdateBinaryBytes() *ExValueScanUpsertBulk { + return u.Update(func(s *ExValueScanUpsert) { + s.UpdateBinaryBytes() + }) +} + // SetBinaryOptional sets the "binary_optional" field. func (u *ExValueScanUpsertBulk) SetBinaryOptional(v *url.URL) *ExValueScanUpsertBulk { return u.Update(func(s *ExValueScanUpsert) { diff --git a/entc/integration/ent/exvaluescan_update.go b/entc/integration/ent/exvaluescan_update.go index c6b3b7fa3..5360ffc9c 100644 --- a/entc/integration/ent/exvaluescan_update.go +++ b/entc/integration/ent/exvaluescan_update.go @@ -40,6 +40,12 @@ func (evsu *ExValueScanUpdate) SetBinary(u *url.URL) *ExValueScanUpdate { return evsu } +// SetBinaryBytes sets the "binary_bytes" field. +func (evsu *ExValueScanUpdate) SetBinaryBytes(u *url.URL) *ExValueScanUpdate { + evsu.mutation.SetBinaryBytes(u) + return evsu +} + // SetBinaryOptional sets the "binary_optional" field. func (evsu *ExValueScanUpdate) SetBinaryOptional(u *url.URL) *ExValueScanUpdate { evsu.mutation.SetBinaryOptional(u) @@ -172,6 +178,13 @@ func (evsu *ExValueScanUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.SetField(exvaluescan.FieldBinary, field.TypeString, vv) } + if value, ok := evsu.mutation.BinaryBytes(); ok { + vv, err := exvaluescan.ValueScanner.BinaryBytes.Value(value) + if err != nil { + return 0, err + } + _spec.SetField(exvaluescan.FieldBinaryBytes, field.TypeBytes, vv) + } if value, ok := evsu.mutation.BinaryOptional(); ok { vv, err := exvaluescan.ValueScanner.BinaryOptional.Value(value) if err != nil { @@ -251,6 +264,12 @@ func (evsuo *ExValueScanUpdateOne) SetBinary(u *url.URL) *ExValueScanUpdateOne { return evsuo } +// SetBinaryBytes sets the "binary_bytes" field. +func (evsuo *ExValueScanUpdateOne) SetBinaryBytes(u *url.URL) *ExValueScanUpdateOne { + evsuo.mutation.SetBinaryBytes(u) + return evsuo +} + // SetBinaryOptional sets the "binary_optional" field. func (evsuo *ExValueScanUpdateOne) SetBinaryOptional(u *url.URL) *ExValueScanUpdateOne { evsuo.mutation.SetBinaryOptional(u) @@ -413,6 +432,13 @@ func (evsuo *ExValueScanUpdateOne) sqlSave(ctx context.Context) (_node *ExValueS } _spec.SetField(exvaluescan.FieldBinary, field.TypeString, vv) } + if value, ok := evsuo.mutation.BinaryBytes(); ok { + vv, err := exvaluescan.ValueScanner.BinaryBytes.Value(value) + if err != nil { + return nil, err + } + _spec.SetField(exvaluescan.FieldBinaryBytes, field.TypeBytes, vv) + } if value, ok := evsuo.mutation.BinaryOptional(); ok { vv, err := exvaluescan.ValueScanner.BinaryOptional.Value(value) if err != nil { diff --git a/entc/integration/ent/migrate/schema.go b/entc/integration/ent/migrate/schema.go index 2214e140b..24f965678 100644 --- a/entc/integration/ent/migrate/schema.go +++ b/entc/integration/ent/migrate/schema.go @@ -94,6 +94,7 @@ var ( ExValueScansColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, {Name: "binary", Type: field.TypeString}, + {Name: "binary_bytes", Type: field.TypeBytes}, {Name: "binary_optional", Type: field.TypeString, Nullable: true}, {Name: "text", Type: field.TypeString}, {Name: "text_optional", Type: field.TypeString, Nullable: true}, diff --git a/entc/integration/ent/mutation.go b/entc/integration/ent/mutation.go index de346a1b2..7c2a9f8d4 100644 --- a/entc/integration/ent/mutation.go +++ b/entc/integration/ent/mutation.go @@ -2137,6 +2137,7 @@ type ExValueScanMutation struct { typ string id *int binary **url.URL + binary_bytes **url.URL binary_optional **url.URL text **big.Int text_optional **big.Int @@ -2283,6 +2284,42 @@ func (m *ExValueScanMutation) ResetBinary() { m.binary = nil } +// SetBinaryBytes sets the "binary_bytes" field. +func (m *ExValueScanMutation) SetBinaryBytes(u *url.URL) { + m.binary_bytes = &u +} + +// BinaryBytes returns the value of the "binary_bytes" field in the mutation. +func (m *ExValueScanMutation) BinaryBytes() (r *url.URL, exists bool) { + v := m.binary_bytes + if v == nil { + return + } + return *v, true +} + +// OldBinaryBytes returns the old "binary_bytes" field's value of the ExValueScan entity. +// If the ExValueScan object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ExValueScanMutation) OldBinaryBytes(ctx context.Context) (v *url.URL, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldBinaryBytes is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldBinaryBytes requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldBinaryBytes: %w", err) + } + return oldValue.BinaryBytes, nil +} + +// ResetBinaryBytes resets all changes to the "binary_bytes" field. +func (m *ExValueScanMutation) ResetBinaryBytes() { + m.binary_bytes = nil +} + // SetBinaryOptional sets the "binary_optional" field. func (m *ExValueScanMutation) SetBinaryOptional(u *url.URL) { m.binary_optional = &u @@ -2572,10 +2609,13 @@ func (m *ExValueScanMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *ExValueScanMutation) Fields() []string { - fields := make([]string, 0, 7) + fields := make([]string, 0, 8) if m.binary != nil { fields = append(fields, exvaluescan.FieldBinary) } + if m.binary_bytes != nil { + fields = append(fields, exvaluescan.FieldBinaryBytes) + } if m.binary_optional != nil { fields = append(fields, exvaluescan.FieldBinaryOptional) } @@ -2604,6 +2644,8 @@ func (m *ExValueScanMutation) Field(name string) (ent.Value, bool) { switch name { case exvaluescan.FieldBinary: return m.Binary() + case exvaluescan.FieldBinaryBytes: + return m.BinaryBytes() case exvaluescan.FieldBinaryOptional: return m.BinaryOptional() case exvaluescan.FieldText: @@ -2627,6 +2669,8 @@ func (m *ExValueScanMutation) OldField(ctx context.Context, name string) (ent.Va switch name { case exvaluescan.FieldBinary: return m.OldBinary(ctx) + case exvaluescan.FieldBinaryBytes: + return m.OldBinaryBytes(ctx) case exvaluescan.FieldBinaryOptional: return m.OldBinaryOptional(ctx) case exvaluescan.FieldText: @@ -2655,6 +2699,13 @@ func (m *ExValueScanMutation) SetField(name string, value ent.Value) error { } m.SetBinary(v) return nil + case exvaluescan.FieldBinaryBytes: + v, ok := value.(*url.URL) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetBinaryBytes(v) + return nil case exvaluescan.FieldBinaryOptional: v, ok := value.(*url.URL) if !ok { @@ -2770,6 +2821,9 @@ func (m *ExValueScanMutation) ResetField(name string) error { case exvaluescan.FieldBinary: m.ResetBinary() return nil + case exvaluescan.FieldBinaryBytes: + m.ResetBinaryBytes() + return nil case exvaluescan.FieldBinaryOptional: m.ResetBinaryOptional() return nil diff --git a/entc/integration/ent/runtime.go b/entc/integration/ent/runtime.go index 1175092f3..c277cdf0d 100644 --- a/entc/integration/ent/runtime.go +++ b/entc/integration/ent/runtime.go @@ -67,23 +67,26 @@ func init() { // exvaluescanDescBinary is the schema descriptor for binary field. exvaluescanDescBinary := exvaluescanFields[0].Descriptor() exvaluescan.ValueScanner.Binary = exvaluescanDescBinary.ValueScanner.(field.TypeValueScanner[*url.URL]) + // exvaluescanDescBinaryBytes is the schema descriptor for binary_bytes field. + exvaluescanDescBinaryBytes := exvaluescanFields[1].Descriptor() + exvaluescan.ValueScanner.BinaryBytes = exvaluescanDescBinaryBytes.ValueScanner.(field.TypeValueScanner[*url.URL]) // exvaluescanDescBinaryOptional is the schema descriptor for binary_optional field. - exvaluescanDescBinaryOptional := exvaluescanFields[1].Descriptor() + exvaluescanDescBinaryOptional := exvaluescanFields[2].Descriptor() exvaluescan.ValueScanner.BinaryOptional = exvaluescanDescBinaryOptional.ValueScanner.(field.TypeValueScanner[*url.URL]) // exvaluescanDescText is the schema descriptor for text field. - exvaluescanDescText := exvaluescanFields[2].Descriptor() + exvaluescanDescText := exvaluescanFields[3].Descriptor() exvaluescan.ValueScanner.Text = exvaluescanDescText.ValueScanner.(field.TypeValueScanner[*big.Int]) // exvaluescanDescTextOptional is the schema descriptor for text_optional field. - exvaluescanDescTextOptional := exvaluescanFields[3].Descriptor() + exvaluescanDescTextOptional := exvaluescanFields[4].Descriptor() exvaluescan.ValueScanner.TextOptional = exvaluescanDescTextOptional.ValueScanner.(field.TypeValueScanner[*big.Int]) // exvaluescanDescBase64 is the schema descriptor for base64 field. - exvaluescanDescBase64 := exvaluescanFields[4].Descriptor() + exvaluescanDescBase64 := exvaluescanFields[5].Descriptor() exvaluescan.ValueScanner.Base64 = exvaluescanDescBase64.ValueScanner.(field.TypeValueScanner[string]) // exvaluescanDescCustom is the schema descriptor for custom field. - exvaluescanDescCustom := exvaluescanFields[5].Descriptor() + exvaluescanDescCustom := exvaluescanFields[6].Descriptor() exvaluescan.ValueScanner.Custom = exvaluescanDescCustom.ValueScanner.(field.TypeValueScanner[string]) // exvaluescanDescCustomOptional is the schema descriptor for custom_optional field. - exvaluescanDescCustomOptional := exvaluescanFields[6].Descriptor() + exvaluescanDescCustomOptional := exvaluescanFields[7].Descriptor() exvaluescan.ValueScanner.CustomOptional = exvaluescanDescCustomOptional.ValueScanner.(field.TypeValueScanner[string]) fieldtypeFields := schema.FieldType{}.Fields() _ = fieldtypeFields diff --git a/entc/integration/ent/schema/exvaluescan.go b/entc/integration/ent/schema/exvaluescan.go index 40028ea22..7bb99144d 100644 --- a/entc/integration/ent/schema/exvaluescan.go +++ b/entc/integration/ent/schema/exvaluescan.go @@ -29,6 +29,9 @@ func (ExValueScan) Fields() []ent.Field { field.String("binary"). GoType(&url.URL{}). ValueScanner(field.BinaryValueScanner[*url.URL]{}), + field.Bytes("binary_bytes"). + GoType(&url.URL{}). + ValueScanner(field.BinaryValueScanner[*url.URL]{}), field.String("binary_optional"). Optional(). GoType(&url.URL{}). diff --git a/entc/integration/gremlin/ent/exvaluescan.go b/entc/integration/gremlin/ent/exvaluescan.go index 07c72c728..aed890f05 100644 --- a/entc/integration/gremlin/ent/exvaluescan.go +++ b/entc/integration/gremlin/ent/exvaluescan.go @@ -22,6 +22,8 @@ type ExValueScan struct { ID string `json:"id,omitempty"` // Binary holds the value of the "binary" field. Binary *url.URL `json:"binary,omitempty"` + // BinaryBytes holds the value of the "binary_bytes" field. + BinaryBytes *url.URL `json:"binary_bytes,omitempty"` // BinaryOptional holds the value of the "binary_optional" field. BinaryOptional *url.URL `json:"binary_optional,omitempty"` // Text holds the value of the "text" field. @@ -45,6 +47,7 @@ func (evs *ExValueScan) FromResponse(res *gremlin.Response) error { var scanevs struct { ID string `json:"id,omitempty"` Binary *url.URL `json:"binary,omitempty"` + BinaryBytes *url.URL `json:"binary_bytes,omitempty"` BinaryOptional *url.URL `json:"binary_optional,omitempty"` Text *big.Int `json:"text,omitempty"` TextOptional *big.Int `json:"text_optional,omitempty"` @@ -57,6 +60,7 @@ func (evs *ExValueScan) FromResponse(res *gremlin.Response) error { } evs.ID = scanevs.ID evs.Binary = scanevs.Binary + evs.BinaryBytes = scanevs.BinaryBytes evs.BinaryOptional = scanevs.BinaryOptional evs.Text = scanevs.Text evs.TextOptional = scanevs.TextOptional @@ -92,6 +96,9 @@ func (evs *ExValueScan) String() string { builder.WriteString("binary=") builder.WriteString(fmt.Sprintf("%v", evs.Binary)) builder.WriteString(", ") + builder.WriteString("binary_bytes=") + builder.WriteString(fmt.Sprintf("%v", evs.BinaryBytes)) + builder.WriteString(", ") builder.WriteString("binary_optional=") builder.WriteString(fmt.Sprintf("%v", evs.BinaryOptional)) builder.WriteString(", ") @@ -125,6 +132,7 @@ func (evs *ExValueScans) FromResponse(res *gremlin.Response) error { var scanevs []struct { ID string `json:"id,omitempty"` Binary *url.URL `json:"binary,omitempty"` + BinaryBytes *url.URL `json:"binary_bytes,omitempty"` BinaryOptional *url.URL `json:"binary_optional,omitempty"` Text *big.Int `json:"text,omitempty"` TextOptional *big.Int `json:"text_optional,omitempty"` @@ -138,6 +146,7 @@ func (evs *ExValueScans) FromResponse(res *gremlin.Response) error { for _, v := range scanevs { node := &ExValueScan{ID: v.ID} node.Binary = v.Binary + node.BinaryBytes = v.BinaryBytes node.BinaryOptional = v.BinaryOptional node.Text = v.Text node.TextOptional = v.TextOptional diff --git a/entc/integration/gremlin/ent/exvaluescan/exvaluescan.go b/entc/integration/gremlin/ent/exvaluescan/exvaluescan.go index b39784471..766a9a443 100644 --- a/entc/integration/gremlin/ent/exvaluescan/exvaluescan.go +++ b/entc/integration/gremlin/ent/exvaluescan/exvaluescan.go @@ -21,6 +21,8 @@ const ( FieldID = "id" // FieldBinary holds the string denoting the binary field in the database. FieldBinary = "binary" + // FieldBinaryBytes holds the string denoting the binary_bytes field in the database. + FieldBinaryBytes = "binary_bytes" // FieldBinaryOptional holds the string denoting the binary_optional field in the database. FieldBinaryOptional = "binary_optional" // FieldText holds the string denoting the text field in the database. @@ -39,6 +41,7 @@ var ( // ValueScanner of all ExValueScan fields. ValueScanner struct { Binary field.TypeValueScanner[*url.URL] + BinaryBytes field.TypeValueScanner[*url.URL] BinaryOptional field.TypeValueScanner[*url.URL] Text field.TypeValueScanner[*big.Int] TextOptional field.TypeValueScanner[*big.Int] diff --git a/entc/integration/gremlin/ent/exvaluescan_create.go b/entc/integration/gremlin/ent/exvaluescan_create.go index bc9f28787..31a17e1ee 100644 --- a/entc/integration/gremlin/ent/exvaluescan_create.go +++ b/entc/integration/gremlin/ent/exvaluescan_create.go @@ -31,6 +31,12 @@ func (evsc *ExValueScanCreate) SetBinary(u *url.URL) *ExValueScanCreate { return evsc } +// SetBinaryBytes sets the "binary_bytes" field. +func (evsc *ExValueScanCreate) SetBinaryBytes(u *url.URL) *ExValueScanCreate { + evsc.mutation.SetBinaryBytes(u) + return evsc +} + // SetBinaryOptional sets the "binary_optional" field. func (evsc *ExValueScanCreate) SetBinaryOptional(u *url.URL) *ExValueScanCreate { evsc.mutation.SetBinaryOptional(u) @@ -112,6 +118,9 @@ func (evsc *ExValueScanCreate) check() error { if _, ok := evsc.mutation.Binary(); !ok { return &ValidationError{Name: "binary", err: errors.New(`ent: missing required field "ExValueScan.binary"`)} } + if _, ok := evsc.mutation.BinaryBytes(); !ok { + return &ValidationError{Name: "binary_bytes", err: errors.New(`ent: missing required field "ExValueScan.binary_bytes"`)} + } if _, ok := evsc.mutation.Text(); !ok { return &ValidationError{Name: "text", err: errors.New(`ent: missing required field "ExValueScan.text"`)} } @@ -150,6 +159,9 @@ func (evsc *ExValueScanCreate) gremlin() *dsl.Traversal { if value, ok := evsc.mutation.Binary(); ok { v.Property(dsl.Single, exvaluescan.FieldBinary, value) } + if value, ok := evsc.mutation.BinaryBytes(); ok { + v.Property(dsl.Single, exvaluescan.FieldBinaryBytes, value) + } if value, ok := evsc.mutation.BinaryOptional(); ok { v.Property(dsl.Single, exvaluescan.FieldBinaryOptional, value) } diff --git a/entc/integration/gremlin/ent/exvaluescan_update.go b/entc/integration/gremlin/ent/exvaluescan_update.go index f1f77a064..a755dfd65 100644 --- a/entc/integration/gremlin/ent/exvaluescan_update.go +++ b/entc/integration/gremlin/ent/exvaluescan_update.go @@ -39,6 +39,12 @@ func (evsu *ExValueScanUpdate) SetBinary(u *url.URL) *ExValueScanUpdate { return evsu } +// SetBinaryBytes sets the "binary_bytes" field. +func (evsu *ExValueScanUpdate) SetBinaryBytes(u *url.URL) *ExValueScanUpdate { + evsu.mutation.SetBinaryBytes(u) + return evsu +} + // SetBinaryOptional sets the "binary_optional" field. func (evsu *ExValueScanUpdate) SetBinaryOptional(u *url.URL) *ExValueScanUpdate { evsu.mutation.SetBinaryOptional(u) @@ -173,6 +179,9 @@ func (evsu *ExValueScanUpdate) gremlin() *dsl.Traversal { if value, ok := evsu.mutation.Binary(); ok { v.Property(dsl.Single, exvaluescan.FieldBinary, value) } + if value, ok := evsu.mutation.BinaryBytes(); ok { + v.Property(dsl.Single, exvaluescan.FieldBinaryBytes, value) + } if value, ok := evsu.mutation.BinaryOptional(); ok { v.Property(dsl.Single, exvaluescan.FieldBinaryOptional, value) } @@ -223,6 +232,12 @@ func (evsuo *ExValueScanUpdateOne) SetBinary(u *url.URL) *ExValueScanUpdateOne { return evsuo } +// SetBinaryBytes sets the "binary_bytes" field. +func (evsuo *ExValueScanUpdateOne) SetBinaryBytes(u *url.URL) *ExValueScanUpdateOne { + evsuo.mutation.SetBinaryBytes(u) + return evsuo +} + // SetBinaryOptional sets the "binary_optional" field. func (evsuo *ExValueScanUpdateOne) SetBinaryOptional(u *url.URL) *ExValueScanUpdateOne { evsuo.mutation.SetBinaryOptional(u) @@ -375,6 +390,9 @@ func (evsuo *ExValueScanUpdateOne) gremlin(id string) *dsl.Traversal { if value, ok := evsuo.mutation.Binary(); ok { v.Property(dsl.Single, exvaluescan.FieldBinary, value) } + if value, ok := evsuo.mutation.BinaryBytes(); ok { + v.Property(dsl.Single, exvaluescan.FieldBinaryBytes, value) + } if value, ok := evsuo.mutation.BinaryOptional(); ok { v.Property(dsl.Single, exvaluescan.FieldBinaryOptional, value) } diff --git a/entc/integration/gremlin/ent/mutation.go b/entc/integration/gremlin/ent/mutation.go index f4c6c7ab3..c6be4782b 100644 --- a/entc/integration/gremlin/ent/mutation.go +++ b/entc/integration/gremlin/ent/mutation.go @@ -2138,6 +2138,7 @@ type ExValueScanMutation struct { typ string id *string binary **url.URL + binary_bytes **url.URL binary_optional **url.URL text **big.Int text_optional **big.Int @@ -2284,6 +2285,42 @@ func (m *ExValueScanMutation) ResetBinary() { m.binary = nil } +// SetBinaryBytes sets the "binary_bytes" field. +func (m *ExValueScanMutation) SetBinaryBytes(u *url.URL) { + m.binary_bytes = &u +} + +// BinaryBytes returns the value of the "binary_bytes" field in the mutation. +func (m *ExValueScanMutation) BinaryBytes() (r *url.URL, exists bool) { + v := m.binary_bytes + if v == nil { + return + } + return *v, true +} + +// OldBinaryBytes returns the old "binary_bytes" field's value of the ExValueScan entity. +// If the ExValueScan object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ExValueScanMutation) OldBinaryBytes(ctx context.Context) (v *url.URL, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldBinaryBytes is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldBinaryBytes requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldBinaryBytes: %w", err) + } + return oldValue.BinaryBytes, nil +} + +// ResetBinaryBytes resets all changes to the "binary_bytes" field. +func (m *ExValueScanMutation) ResetBinaryBytes() { + m.binary_bytes = nil +} + // SetBinaryOptional sets the "binary_optional" field. func (m *ExValueScanMutation) SetBinaryOptional(u *url.URL) { m.binary_optional = &u @@ -2573,10 +2610,13 @@ func (m *ExValueScanMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *ExValueScanMutation) Fields() []string { - fields := make([]string, 0, 7) + fields := make([]string, 0, 8) if m.binary != nil { fields = append(fields, exvaluescan.FieldBinary) } + if m.binary_bytes != nil { + fields = append(fields, exvaluescan.FieldBinaryBytes) + } if m.binary_optional != nil { fields = append(fields, exvaluescan.FieldBinaryOptional) } @@ -2605,6 +2645,8 @@ func (m *ExValueScanMutation) Field(name string) (ent.Value, bool) { switch name { case exvaluescan.FieldBinary: return m.Binary() + case exvaluescan.FieldBinaryBytes: + return m.BinaryBytes() case exvaluescan.FieldBinaryOptional: return m.BinaryOptional() case exvaluescan.FieldText: @@ -2628,6 +2670,8 @@ func (m *ExValueScanMutation) OldField(ctx context.Context, name string) (ent.Va switch name { case exvaluescan.FieldBinary: return m.OldBinary(ctx) + case exvaluescan.FieldBinaryBytes: + return m.OldBinaryBytes(ctx) case exvaluescan.FieldBinaryOptional: return m.OldBinaryOptional(ctx) case exvaluescan.FieldText: @@ -2656,6 +2700,13 @@ func (m *ExValueScanMutation) SetField(name string, value ent.Value) error { } m.SetBinary(v) return nil + case exvaluescan.FieldBinaryBytes: + v, ok := value.(*url.URL) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetBinaryBytes(v) + return nil case exvaluescan.FieldBinaryOptional: v, ok := value.(*url.URL) if !ok { @@ -2771,6 +2822,9 @@ func (m *ExValueScanMutation) ResetField(name string) error { case exvaluescan.FieldBinary: m.ResetBinary() return nil + case exvaluescan.FieldBinaryBytes: + m.ResetBinaryBytes() + return nil case exvaluescan.FieldBinaryOptional: m.ResetBinaryOptional() return nil diff --git a/entc/integration/gremlin/ent/runtime.go b/entc/integration/gremlin/ent/runtime.go index 0a43cfc96..d8ec9fb54 100644 --- a/entc/integration/gremlin/ent/runtime.go +++ b/entc/integration/gremlin/ent/runtime.go @@ -67,23 +67,26 @@ func init() { // exvaluescanDescBinary is the schema descriptor for binary field. exvaluescanDescBinary := exvaluescanFields[0].Descriptor() exvaluescan.ValueScanner.Binary = exvaluescanDescBinary.ValueScanner.(field.TypeValueScanner[*url.URL]) + // exvaluescanDescBinaryBytes is the schema descriptor for binary_bytes field. + exvaluescanDescBinaryBytes := exvaluescanFields[1].Descriptor() + exvaluescan.ValueScanner.BinaryBytes = exvaluescanDescBinaryBytes.ValueScanner.(field.TypeValueScanner[*url.URL]) // exvaluescanDescBinaryOptional is the schema descriptor for binary_optional field. - exvaluescanDescBinaryOptional := exvaluescanFields[1].Descriptor() + exvaluescanDescBinaryOptional := exvaluescanFields[2].Descriptor() exvaluescan.ValueScanner.BinaryOptional = exvaluescanDescBinaryOptional.ValueScanner.(field.TypeValueScanner[*url.URL]) // exvaluescanDescText is the schema descriptor for text field. - exvaluescanDescText := exvaluescanFields[2].Descriptor() + exvaluescanDescText := exvaluescanFields[3].Descriptor() exvaluescan.ValueScanner.Text = exvaluescanDescText.ValueScanner.(field.TypeValueScanner[*big.Int]) // exvaluescanDescTextOptional is the schema descriptor for text_optional field. - exvaluescanDescTextOptional := exvaluescanFields[3].Descriptor() + exvaluescanDescTextOptional := exvaluescanFields[4].Descriptor() exvaluescan.ValueScanner.TextOptional = exvaluescanDescTextOptional.ValueScanner.(field.TypeValueScanner[*big.Int]) // exvaluescanDescBase64 is the schema descriptor for base64 field. - exvaluescanDescBase64 := exvaluescanFields[4].Descriptor() + exvaluescanDescBase64 := exvaluescanFields[5].Descriptor() exvaluescan.ValueScanner.Base64 = exvaluescanDescBase64.ValueScanner.(field.TypeValueScanner[string]) // exvaluescanDescCustom is the schema descriptor for custom field. - exvaluescanDescCustom := exvaluescanFields[5].Descriptor() + exvaluescanDescCustom := exvaluescanFields[6].Descriptor() exvaluescan.ValueScanner.Custom = exvaluescanDescCustom.ValueScanner.(field.TypeValueScanner[string]) // exvaluescanDescCustomOptional is the schema descriptor for custom_optional field. - exvaluescanDescCustomOptional := exvaluescanFields[6].Descriptor() + exvaluescanDescCustomOptional := exvaluescanFields[7].Descriptor() exvaluescan.ValueScanner.CustomOptional = exvaluescanDescCustomOptional.ValueScanner.(field.TypeValueScanner[string]) fieldtypeFields := schema.FieldType{}.Fields() _ = fieldtypeFields diff --git a/entc/integration/integration_test.go b/entc/integration/integration_test.go index 0e77bddee..c1678d623 100644 --- a/entc/integration/integration_test.go +++ b/entc/integration/integration_test.go @@ -2353,10 +2353,11 @@ func ExtValueScan(t *testing.T, client *ent.Client) { ctx := context.Background() u, err := url.Parse("https://entgo.io") require.NoError(t, err) - check := func(ex *ent.ExValueScan, i *big.Int, u, b64, custom string) { + check := func(ex *ent.ExValueScan, i *big.Int, u, b64, custom string, ub *url.URL) { for _, e := range []*ent.ExValueScan{ex, client.ExValueScan.GetX(ctx, ex.ID)} { require.Equal(t, i, e.Text) require.Equal(t, u, e.Binary.String()) + require.Equal(t, ub, e.BinaryBytes) require.Equal(t, b64, e.Base64) require.Equal(t, custom, e.Custom) } @@ -2364,31 +2365,42 @@ func ExtValueScan(t *testing.T, client *ent.Client) { ex := client.ExValueScan.Create(). SetText(big.NewInt(10)). SetBinary(u). + SetBinaryBytes(u). SetBase64("a8m"). SetCustom("atlasgo.io"). SaveX(ctx) - check(ex, big.NewInt(10), u.String(), "a8m", "atlasgo.io") + check(ex, big.NewInt(10), u.String(), "a8m", "atlasgo.io", u) // Ensure the database values store as expected. var raw []struct { - Text string - Binary string - Base64 string - Custom string + Text string + Binary string + BinaryBytes []byte `sql:"binary_bytes"` + Base64 string + Custom string } client.ExValueScan.Query(). - Select(exvaluescan.FieldText, exvaluescan.FieldBinary, exvaluescan.FieldBase64, exvaluescan.FieldCustom). + Select( + exvaluescan.FieldText, + exvaluescan.FieldBinary, + exvaluescan.FieldBinaryBytes, + exvaluescan.FieldBase64, + exvaluescan.FieldCustom, + ). ScanX(ctx, &raw) require.Len(t, raw, 1) require.Equal(t, "10", raw[0].Text) require.Equal(t, u.String(), raw[0].Binary) + ub, err := u.MarshalBinary() + require.NoError(t, err) + require.Equal(t, ub, raw[0].BinaryBytes) require.Equal(t, base64.StdEncoding.EncodeToString([]byte(ex.Base64)), raw[0].Base64) require.Equal(t, "0x:"+hex.EncodeToString([]byte(ex.Custom)), raw[0].Custom) // Update the values and ensure they are updated as expected. u.Path = "/docs" - ex = ex.Update().SetBinary(u).SetText(big.NewInt(20)).SetBase64("m8a").SetCustom("entgo.io").SaveX(ctx) - check(ex, big.NewInt(20), u.String(), "m8a", "entgo.io") + ex = ex.Update().SetBinary(u).SetBinaryBytes(u).SetText(big.NewInt(20)).SetBase64("m8a").SetCustom("entgo.io").SaveX(ctx) + check(ex, big.NewInt(20), u.String(), "m8a", "entgo.io", u) // Check predicates. require.True(t, client.ExValueScan.Query().Where(exvaluescan.Text(big.NewInt(20))).ExistX(ctx)) diff --git a/schema/field/field.go b/schema/field/field.go index d991b88c0..e06febb5d 100644 --- a/schema/field/field.go +++ b/schema/field/field.go @@ -691,6 +691,15 @@ func (b *bytesBuilder) GoType(typ any) *bytesBuilder { return b } +// ValueScanner provides an external value scanner for the given GoType. +// Using this option allow users to use field types that do not implement +// the sql.Scanner and driver.Valuer interfaces, such as slices and maps +// or types exist in external packages (e.g., url.URL). +func (b *bytesBuilder) ValueScanner(vs any) *bytesBuilder { + b.desc.ValueScanner = vs + return b +} + // Annotations adds a list of annotations to the field object to be used by // codegen extensions. func (b *bytesBuilder) Annotations(annotations ...schema.Annotation) *bytesBuilder { diff --git a/schema/field/field_test.go b/schema/field/field_test.go index 24b73b281..120649c92 100644 --- a/schema/field/field_test.go +++ b/schema/field/field_test.go @@ -8,6 +8,7 @@ import ( "database/sql" "database/sql/driver" "encoding/base64" + "encoding/hex" "errors" "fmt" "io" @@ -289,6 +290,58 @@ func TestBytes_DefaultFunc(t *testing.T) { assert.EqualError(t, fd.Err, `field.Bytes("ip").DefaultFunc expects func but got slice`) } +type nullBytes []byte + +func (b *nullBytes) Scan(v any) error { + if v == nil { + return nil + } + switch v := v.(type) { + case []byte: + *b = v + return nil + case string: + *b = []byte(v) + return nil + default: + return errors.New("unexpected type") + } +} + +func (b nullBytes) Value() (driver.Value, error) { return b, nil } + +func TestBytes_ValueScanner(t *testing.T) { + fd := field.Bytes("dir"). + ValueScanner(field.ValueScannerFunc[[]byte, *nullBytes]{ + V: func(s []byte) (driver.Value, error) { + return []byte(hex.EncodeToString(s)), nil + }, + S: func(ns *nullBytes) ([]byte, error) { + if ns == nil { + return nil, nil + } + b, err := hex.DecodeString(string(*ns)) + if err != nil { + return nil, err + } + return b, nil + }, + }).Descriptor() + require.NoError(t, fd.Err) + require.NotNil(t, fd.ValueScanner) + _, ok := fd.ValueScanner.(field.ValueScannerFunc[[]byte, *nullBytes]) + require.True(t, ok) + + fd = field.Bytes("url"). + GoType(&url.URL{}). + ValueScanner(field.BinaryValueScanner[*url.URL]{}). + Descriptor() + require.NoError(t, fd.Err) + require.NotNil(t, fd.ValueScanner) + _, ok = fd.ValueScanner.(field.TypeValueScanner[*url.URL]) + require.True(t, ok) +} + func TestString_DefaultFunc(t *testing.T) { f1 := func() http.Dir { return "/tmp" } fd := field.String("dir").GoType(http.Dir("/tmp")).DefaultFunc(f1).Descriptor()