From c89cf5e5356ece63436308d057dbadb8d021043e Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 18:48:11 +0200 Subject: [PATCH 01/10] Add Ent schemas and generated code for the five domain models Introduce ent/schema for Component, ComponentAttr, Incident, IncidentStatus and NotificationOutbox, matching the production DDL (serial ids, timestamp vs timestamptz, partial outbox indexes, varchar-backed type enum). Codegen is wired via go:generate with the sql/upsert and sql/versioned-migration features. GORM remains the active backend; this commit only adds the Ent layer so the DB facade can be swapped over incrementally. --- ent/client.go | 1011 ++++ ent/component.go | 181 + ent/component/component.go | 141 + ent/component/where.go | 352 ++ ent/component_create.go | 788 +++ ent/component_delete.go | 88 + ent/component_query.go | 711 +++ ent/component_update.go | 718 +++ ent/componentattr.go | 154 + ent/componentattr/componentattr.go | 94 + ent/componentattr/where.go | 267 + ent/componentattr_create.go | 644 +++ ent/componentattr_delete.go | 88 + ent/componentattr_query.go | 606 +++ ent/componentattr_update.go | 400 ++ ent/ent.go | 616 +++ ent/enttest/enttest.go | 84 + ent/generate.go | 9 + ent/hook/hook.go | 247 + ent/incident.go | 293 ++ ent/incident/incident.go | 251 + ent/incident/where.go | 897 ++++ ent/incident_create.go | 1518 ++++++ ent/incident_delete.go | 88 + ent/incident_query.go | 711 +++ ent/incident_update.go | 1198 +++++ ent/incidentstatus.go | 194 + ent/incidentstatus/incidentstatus.go | 118 + ent/incidentstatus/where.go | 635 +++ ent/incidentstatus_create.go | 1089 ++++ ent/incidentstatus_delete.go | 88 + ent/incidentstatus_query.go | 527 ++ ent/incidentstatus_update.go | 646 +++ ent/migrate/migrate.go | 96 + ent/migrate/schema.go | 257 + ent/mutation.go | 4840 ++++++++++++++++++ ent/notificationoutbox.go | 283 + ent/notificationoutbox/notificationoutbox.go | 185 + ent/notificationoutbox/where.go | 874 ++++ ent/notificationoutbox_create.go | 1360 +++++ ent/notificationoutbox_delete.go | 88 + ent/notificationoutbox_query.go | 606 +++ ent/notificationoutbox_update.go | 865 ++++ ent/predicate/predicate.go | 22 + ent/runtime.go | 84 + ent/runtime/runtime.go | 10 + ent/schema/component.go | 52 + ent/schema/componentattr.go | 53 + ent/schema/incident.go | 78 + ent/schema/incidentstatus.go | 57 + ent/schema/notificationoutbox.go | 88 + ent/tx.go | 222 + go.mod | 26 + go.sum | 53 + 54 files changed, 25651 insertions(+) create mode 100644 ent/client.go create mode 100644 ent/component.go create mode 100644 ent/component/component.go create mode 100644 ent/component/where.go create mode 100644 ent/component_create.go create mode 100644 ent/component_delete.go create mode 100644 ent/component_query.go create mode 100644 ent/component_update.go create mode 100644 ent/componentattr.go create mode 100644 ent/componentattr/componentattr.go create mode 100644 ent/componentattr/where.go create mode 100644 ent/componentattr_create.go create mode 100644 ent/componentattr_delete.go create mode 100644 ent/componentattr_query.go create mode 100644 ent/componentattr_update.go create mode 100644 ent/ent.go create mode 100644 ent/enttest/enttest.go create mode 100644 ent/generate.go create mode 100644 ent/hook/hook.go create mode 100644 ent/incident.go create mode 100644 ent/incident/incident.go create mode 100644 ent/incident/where.go create mode 100644 ent/incident_create.go create mode 100644 ent/incident_delete.go create mode 100644 ent/incident_query.go create mode 100644 ent/incident_update.go create mode 100644 ent/incidentstatus.go create mode 100644 ent/incidentstatus/incidentstatus.go create mode 100644 ent/incidentstatus/where.go create mode 100644 ent/incidentstatus_create.go create mode 100644 ent/incidentstatus_delete.go create mode 100644 ent/incidentstatus_query.go create mode 100644 ent/incidentstatus_update.go create mode 100644 ent/migrate/migrate.go create mode 100644 ent/migrate/schema.go create mode 100644 ent/mutation.go create mode 100644 ent/notificationoutbox.go create mode 100644 ent/notificationoutbox/notificationoutbox.go create mode 100644 ent/notificationoutbox/where.go create mode 100644 ent/notificationoutbox_create.go create mode 100644 ent/notificationoutbox_delete.go create mode 100644 ent/notificationoutbox_query.go create mode 100644 ent/notificationoutbox_update.go create mode 100644 ent/predicate/predicate.go create mode 100644 ent/runtime.go create mode 100644 ent/runtime/runtime.go create mode 100644 ent/schema/component.go create mode 100644 ent/schema/componentattr.go create mode 100644 ent/schema/incident.go create mode 100644 ent/schema/incidentstatus.go create mode 100644 ent/schema/notificationoutbox.go create mode 100644 ent/tx.go diff --git a/ent/client.go b/ent/client.go new file mode 100644 index 0000000..6d62444 --- /dev/null +++ b/ent/client.go @@ -0,0 +1,1011 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "log" + "reflect" + + "github.com/stackmon/otc-status-dashboard/ent/migrate" + + "entgo.io/ent" + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" +) + +// Client is the client that holds all ent builders. +type Client struct { + config + // Schema is the client for creating, migrating and dropping schema. + Schema *migrate.Schema + // Component is the client for interacting with the Component builders. + Component *ComponentClient + // ComponentAttr is the client for interacting with the ComponentAttr builders. + ComponentAttr *ComponentAttrClient + // Incident is the client for interacting with the Incident builders. + Incident *IncidentClient + // IncidentStatus is the client for interacting with the IncidentStatus builders. + IncidentStatus *IncidentStatusClient + // NotificationOutbox is the client for interacting with the NotificationOutbox builders. + NotificationOutbox *NotificationOutboxClient +} + +// NewClient creates a new client configured with the given options. +func NewClient(opts ...Option) *Client { + client := &Client{config: newConfig(opts...)} + client.init() + return client +} + +func (c *Client) init() { + c.Schema = migrate.NewSchema(c.driver) + c.Component = NewComponentClient(c.config) + c.ComponentAttr = NewComponentAttrClient(c.config) + c.Incident = NewIncidentClient(c.config) + c.IncidentStatus = NewIncidentStatusClient(c.config) + c.NotificationOutbox = NewNotificationOutboxClient(c.config) +} + +type ( + // config is the configuration for the client and its builder. + config struct { + // driver used for executing database requests. + driver dialect.Driver + // debug enable a debug logging. + debug bool + // log used for logging on debug mode. + log func(...any) + // hooks to execute on mutations. + hooks *hooks + // interceptors to execute on queries. + inters *inters + } + // Option function to configure the client. + Option func(*config) +) + +// newConfig creates a new config for the client. +func newConfig(opts ...Option) config { + cfg := config{log: log.Println, hooks: &hooks{}, inters: &inters{}} + cfg.options(opts...) + return cfg +} + +// options applies the options on the config object. +func (c *config) options(opts ...Option) { + for _, opt := range opts { + opt(c) + } + if c.debug { + c.driver = dialect.Debug(c.driver, c.log) + } +} + +// Debug enables debug logging on the ent.Driver. +func Debug() Option { + return func(c *config) { + c.debug = true + } +} + +// Log sets the logging function for debug mode. +func Log(fn func(...any)) Option { + return func(c *config) { + c.log = fn + } +} + +// Driver configures the client driver. +func Driver(driver dialect.Driver) Option { + return func(c *config) { + c.driver = driver + } +} + +// Open opens a database/sql.DB specified by the driver name and +// the data source name, and returns a new client attached to it. +// Optional parameters can be added for configuring the client. +func Open(driverName, dataSourceName string, options ...Option) (*Client, error) { + switch driverName { + case dialect.MySQL, dialect.Postgres, dialect.SQLite: + drv, err := sql.Open(driverName, dataSourceName) + if err != nil { + return nil, err + } + return NewClient(append(options, Driver(drv))...), nil + default: + return nil, fmt.Errorf("unsupported driver: %q", driverName) + } +} + +// ErrTxStarted is returned when trying to start a new transaction from a transactional client. +var ErrTxStarted = errors.New("ent: cannot start a transaction within a transaction") + +// Tx returns a new transactional client. The provided context +// is used until the transaction is committed or rolled back. +func (c *Client) Tx(ctx context.Context) (*Tx, error) { + if _, ok := c.driver.(*txDriver); ok { + return nil, ErrTxStarted + } + tx, err := newTx(ctx, c.driver) + if err != nil { + return nil, fmt.Errorf("ent: starting a transaction: %w", err) + } + cfg := c.config + cfg.driver = tx + return &Tx{ + ctx: ctx, + config: cfg, + Component: NewComponentClient(cfg), + ComponentAttr: NewComponentAttrClient(cfg), + Incident: NewIncidentClient(cfg), + IncidentStatus: NewIncidentStatusClient(cfg), + NotificationOutbox: NewNotificationOutboxClient(cfg), + }, nil +} + +// BeginTx returns a transactional client with specified options. +func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) { + if _, ok := c.driver.(*txDriver); ok { + return nil, errors.New("ent: cannot start a transaction within a transaction") + } + tx, err := c.driver.(interface { + BeginTx(context.Context, *sql.TxOptions) (dialect.Tx, error) + }).BeginTx(ctx, opts) + if err != nil { + return nil, fmt.Errorf("ent: starting a transaction: %w", err) + } + cfg := c.config + cfg.driver = &txDriver{tx: tx, drv: c.driver} + return &Tx{ + ctx: ctx, + config: cfg, + Component: NewComponentClient(cfg), + ComponentAttr: NewComponentAttrClient(cfg), + Incident: NewIncidentClient(cfg), + IncidentStatus: NewIncidentStatusClient(cfg), + NotificationOutbox: NewNotificationOutboxClient(cfg), + }, nil +} + +// Debug returns a new debug-client. It's used to get verbose logging on specific operations. +// +// client.Debug(). +// Component. +// Query(). +// Count(ctx) +func (c *Client) Debug() *Client { + if c.debug { + return c + } + cfg := c.config + cfg.driver = dialect.Debug(c.driver, c.log) + client := &Client{config: cfg} + client.init() + return client +} + +// Close closes the database connection and prevents new queries from starting. +func (c *Client) Close() error { + return c.driver.Close() +} + +// Use adds the mutation hooks to all the entity clients. +// In order to add hooks to a specific client, call: `client.Node.Use(...)`. +func (c *Client) Use(hooks ...Hook) { + c.Component.Use(hooks...) + c.ComponentAttr.Use(hooks...) + c.Incident.Use(hooks...) + c.IncidentStatus.Use(hooks...) + c.NotificationOutbox.Use(hooks...) +} + +// Intercept adds the query interceptors to all the entity clients. +// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`. +func (c *Client) Intercept(interceptors ...Interceptor) { + c.Component.Intercept(interceptors...) + c.ComponentAttr.Intercept(interceptors...) + c.Incident.Intercept(interceptors...) + c.IncidentStatus.Intercept(interceptors...) + c.NotificationOutbox.Intercept(interceptors...) +} + +// Mutate implements the ent.Mutator interface. +func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { + switch m := m.(type) { + case *ComponentMutation: + return c.Component.mutate(ctx, m) + case *ComponentAttrMutation: + return c.ComponentAttr.mutate(ctx, m) + case *IncidentMutation: + return c.Incident.mutate(ctx, m) + case *IncidentStatusMutation: + return c.IncidentStatus.mutate(ctx, m) + case *NotificationOutboxMutation: + return c.NotificationOutbox.mutate(ctx, m) + default: + return nil, fmt.Errorf("ent: unknown mutation type %T", m) + } +} + +// ComponentClient is a client for the Component schema. +type ComponentClient struct { + config +} + +// NewComponentClient returns a client for the Component from the given config. +func NewComponentClient(c config) *ComponentClient { + return &ComponentClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `component.Hooks(f(g(h())))`. +func (c *ComponentClient) Use(hooks ...Hook) { + c.hooks.Component = append(c.hooks.Component, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `component.Intercept(f(g(h())))`. +func (c *ComponentClient) Intercept(interceptors ...Interceptor) { + c.inters.Component = append(c.inters.Component, interceptors...) +} + +// Create returns a builder for creating a Component entity. +func (c *ComponentClient) Create() *ComponentCreate { + mutation := newComponentMutation(c.config, OpCreate) + return &ComponentCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Component entities. +func (c *ComponentClient) CreateBulk(builders ...*ComponentCreate) *ComponentCreateBulk { + return &ComponentCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *ComponentClient) MapCreateBulk(slice any, setFunc func(*ComponentCreate, int)) *ComponentCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &ComponentCreateBulk{err: fmt.Errorf("calling to ComponentClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*ComponentCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &ComponentCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Component. +func (c *ComponentClient) Update() *ComponentUpdate { + mutation := newComponentMutation(c.config, OpUpdate) + return &ComponentUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *ComponentClient) UpdateOne(_m *Component) *ComponentUpdateOne { + mutation := newComponentMutation(c.config, OpUpdateOne, withComponent(_m)) + return &ComponentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *ComponentClient) UpdateOneID(id int) *ComponentUpdateOne { + mutation := newComponentMutation(c.config, OpUpdateOne, withComponentID(id)) + return &ComponentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Component. +func (c *ComponentClient) Delete() *ComponentDelete { + mutation := newComponentMutation(c.config, OpDelete) + return &ComponentDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *ComponentClient) DeleteOne(_m *Component) *ComponentDeleteOne { + return c.DeleteOneID(_m.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *ComponentClient) DeleteOneID(id int) *ComponentDeleteOne { + builder := c.Delete().Where(component.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &ComponentDeleteOne{builder} +} + +// Query returns a query builder for Component. +func (c *ComponentClient) Query() *ComponentQuery { + return &ComponentQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeComponent}, + inters: c.Interceptors(), + } +} + +// Get returns a Component entity by its id. +func (c *ComponentClient) Get(ctx context.Context, id int) (*Component, error) { + return c.Query().Where(component.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *ComponentClient) GetX(ctx context.Context, id int) *Component { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryAttributes queries the attributes edge of a Component. +func (c *ComponentClient) QueryAttributes(_m *Component) *ComponentAttrQuery { + query := (&ComponentAttrClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := _m.ID + step := sqlgraph.NewStep( + sqlgraph.From(component.Table, component.FieldID, id), + sqlgraph.To(componentattr.Table, componentattr.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, component.AttributesTable, component.AttributesColumn), + ) + fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryIncidents queries the incidents edge of a Component. +func (c *ComponentClient) QueryIncidents(_m *Component) *IncidentQuery { + query := (&IncidentClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := _m.ID + step := sqlgraph.NewStep( + sqlgraph.From(component.Table, component.FieldID, id), + sqlgraph.To(incident.Table, incident.FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, component.IncidentsTable, component.IncidentsPrimaryKey...), + ) + fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *ComponentClient) Hooks() []Hook { + return c.hooks.Component +} + +// Interceptors returns the client interceptors. +func (c *ComponentClient) Interceptors() []Interceptor { + return c.inters.Component +} + +func (c *ComponentClient) mutate(ctx context.Context, m *ComponentMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&ComponentCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&ComponentUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&ComponentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&ComponentDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown Component mutation op: %q", m.Op()) + } +} + +// ComponentAttrClient is a client for the ComponentAttr schema. +type ComponentAttrClient struct { + config +} + +// NewComponentAttrClient returns a client for the ComponentAttr from the given config. +func NewComponentAttrClient(c config) *ComponentAttrClient { + return &ComponentAttrClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `componentattr.Hooks(f(g(h())))`. +func (c *ComponentAttrClient) Use(hooks ...Hook) { + c.hooks.ComponentAttr = append(c.hooks.ComponentAttr, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `componentattr.Intercept(f(g(h())))`. +func (c *ComponentAttrClient) Intercept(interceptors ...Interceptor) { + c.inters.ComponentAttr = append(c.inters.ComponentAttr, interceptors...) +} + +// Create returns a builder for creating a ComponentAttr entity. +func (c *ComponentAttrClient) Create() *ComponentAttrCreate { + mutation := newComponentAttrMutation(c.config, OpCreate) + return &ComponentAttrCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of ComponentAttr entities. +func (c *ComponentAttrClient) CreateBulk(builders ...*ComponentAttrCreate) *ComponentAttrCreateBulk { + return &ComponentAttrCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *ComponentAttrClient) MapCreateBulk(slice any, setFunc func(*ComponentAttrCreate, int)) *ComponentAttrCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &ComponentAttrCreateBulk{err: fmt.Errorf("calling to ComponentAttrClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*ComponentAttrCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &ComponentAttrCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for ComponentAttr. +func (c *ComponentAttrClient) Update() *ComponentAttrUpdate { + mutation := newComponentAttrMutation(c.config, OpUpdate) + return &ComponentAttrUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *ComponentAttrClient) UpdateOne(_m *ComponentAttr) *ComponentAttrUpdateOne { + mutation := newComponentAttrMutation(c.config, OpUpdateOne, withComponentAttr(_m)) + return &ComponentAttrUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *ComponentAttrClient) UpdateOneID(id int) *ComponentAttrUpdateOne { + mutation := newComponentAttrMutation(c.config, OpUpdateOne, withComponentAttrID(id)) + return &ComponentAttrUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for ComponentAttr. +func (c *ComponentAttrClient) Delete() *ComponentAttrDelete { + mutation := newComponentAttrMutation(c.config, OpDelete) + return &ComponentAttrDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *ComponentAttrClient) DeleteOne(_m *ComponentAttr) *ComponentAttrDeleteOne { + return c.DeleteOneID(_m.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *ComponentAttrClient) DeleteOneID(id int) *ComponentAttrDeleteOne { + builder := c.Delete().Where(componentattr.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &ComponentAttrDeleteOne{builder} +} + +// Query returns a query builder for ComponentAttr. +func (c *ComponentAttrClient) Query() *ComponentAttrQuery { + return &ComponentAttrQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeComponentAttr}, + inters: c.Interceptors(), + } +} + +// Get returns a ComponentAttr entity by its id. +func (c *ComponentAttrClient) Get(ctx context.Context, id int) (*ComponentAttr, error) { + return c.Query().Where(componentattr.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *ComponentAttrClient) GetX(ctx context.Context, id int) *ComponentAttr { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryComponent queries the component edge of a ComponentAttr. +func (c *ComponentAttrClient) QueryComponent(_m *ComponentAttr) *ComponentQuery { + query := (&ComponentClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := _m.ID + step := sqlgraph.NewStep( + sqlgraph.From(componentattr.Table, componentattr.FieldID, id), + sqlgraph.To(component.Table, component.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, componentattr.ComponentTable, componentattr.ComponentColumn), + ) + fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *ComponentAttrClient) Hooks() []Hook { + return c.hooks.ComponentAttr +} + +// Interceptors returns the client interceptors. +func (c *ComponentAttrClient) Interceptors() []Interceptor { + return c.inters.ComponentAttr +} + +func (c *ComponentAttrClient) mutate(ctx context.Context, m *ComponentAttrMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&ComponentAttrCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&ComponentAttrUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&ComponentAttrUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&ComponentAttrDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown ComponentAttr mutation op: %q", m.Op()) + } +} + +// IncidentClient is a client for the Incident schema. +type IncidentClient struct { + config +} + +// NewIncidentClient returns a client for the Incident from the given config. +func NewIncidentClient(c config) *IncidentClient { + return &IncidentClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `incident.Hooks(f(g(h())))`. +func (c *IncidentClient) Use(hooks ...Hook) { + c.hooks.Incident = append(c.hooks.Incident, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `incident.Intercept(f(g(h())))`. +func (c *IncidentClient) Intercept(interceptors ...Interceptor) { + c.inters.Incident = append(c.inters.Incident, interceptors...) +} + +// Create returns a builder for creating a Incident entity. +func (c *IncidentClient) Create() *IncidentCreate { + mutation := newIncidentMutation(c.config, OpCreate) + return &IncidentCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Incident entities. +func (c *IncidentClient) CreateBulk(builders ...*IncidentCreate) *IncidentCreateBulk { + return &IncidentCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *IncidentClient) MapCreateBulk(slice any, setFunc func(*IncidentCreate, int)) *IncidentCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &IncidentCreateBulk{err: fmt.Errorf("calling to IncidentClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*IncidentCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &IncidentCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Incident. +func (c *IncidentClient) Update() *IncidentUpdate { + mutation := newIncidentMutation(c.config, OpUpdate) + return &IncidentUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *IncidentClient) UpdateOne(_m *Incident) *IncidentUpdateOne { + mutation := newIncidentMutation(c.config, OpUpdateOne, withIncident(_m)) + return &IncidentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *IncidentClient) UpdateOneID(id int) *IncidentUpdateOne { + mutation := newIncidentMutation(c.config, OpUpdateOne, withIncidentID(id)) + return &IncidentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Incident. +func (c *IncidentClient) Delete() *IncidentDelete { + mutation := newIncidentMutation(c.config, OpDelete) + return &IncidentDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *IncidentClient) DeleteOne(_m *Incident) *IncidentDeleteOne { + return c.DeleteOneID(_m.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *IncidentClient) DeleteOneID(id int) *IncidentDeleteOne { + builder := c.Delete().Where(incident.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &IncidentDeleteOne{builder} +} + +// Query returns a query builder for Incident. +func (c *IncidentClient) Query() *IncidentQuery { + return &IncidentQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeIncident}, + inters: c.Interceptors(), + } +} + +// Get returns a Incident entity by its id. +func (c *IncidentClient) Get(ctx context.Context, id int) (*Incident, error) { + return c.Query().Where(incident.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *IncidentClient) GetX(ctx context.Context, id int) *Incident { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryComponents queries the components edge of a Incident. +func (c *IncidentClient) QueryComponents(_m *Incident) *ComponentQuery { + query := (&ComponentClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := _m.ID + step := sqlgraph.NewStep( + sqlgraph.From(incident.Table, incident.FieldID, id), + sqlgraph.To(component.Table, component.FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, incident.ComponentsTable, incident.ComponentsPrimaryKey...), + ) + fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryNotifications queries the notifications edge of a Incident. +func (c *IncidentClient) QueryNotifications(_m *Incident) *NotificationOutboxQuery { + query := (&NotificationOutboxClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := _m.ID + step := sqlgraph.NewStep( + sqlgraph.From(incident.Table, incident.FieldID, id), + sqlgraph.To(notificationoutbox.Table, notificationoutbox.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, incident.NotificationsTable, incident.NotificationsColumn), + ) + fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *IncidentClient) Hooks() []Hook { + return c.hooks.Incident +} + +// Interceptors returns the client interceptors. +func (c *IncidentClient) Interceptors() []Interceptor { + return c.inters.Incident +} + +func (c *IncidentClient) mutate(ctx context.Context, m *IncidentMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&IncidentCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&IncidentUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&IncidentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&IncidentDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown Incident mutation op: %q", m.Op()) + } +} + +// IncidentStatusClient is a client for the IncidentStatus schema. +type IncidentStatusClient struct { + config +} + +// NewIncidentStatusClient returns a client for the IncidentStatus from the given config. +func NewIncidentStatusClient(c config) *IncidentStatusClient { + return &IncidentStatusClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `incidentstatus.Hooks(f(g(h())))`. +func (c *IncidentStatusClient) Use(hooks ...Hook) { + c.hooks.IncidentStatus = append(c.hooks.IncidentStatus, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `incidentstatus.Intercept(f(g(h())))`. +func (c *IncidentStatusClient) Intercept(interceptors ...Interceptor) { + c.inters.IncidentStatus = append(c.inters.IncidentStatus, interceptors...) +} + +// Create returns a builder for creating a IncidentStatus entity. +func (c *IncidentStatusClient) Create() *IncidentStatusCreate { + mutation := newIncidentStatusMutation(c.config, OpCreate) + return &IncidentStatusCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of IncidentStatus entities. +func (c *IncidentStatusClient) CreateBulk(builders ...*IncidentStatusCreate) *IncidentStatusCreateBulk { + return &IncidentStatusCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *IncidentStatusClient) MapCreateBulk(slice any, setFunc func(*IncidentStatusCreate, int)) *IncidentStatusCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &IncidentStatusCreateBulk{err: fmt.Errorf("calling to IncidentStatusClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*IncidentStatusCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &IncidentStatusCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for IncidentStatus. +func (c *IncidentStatusClient) Update() *IncidentStatusUpdate { + mutation := newIncidentStatusMutation(c.config, OpUpdate) + return &IncidentStatusUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *IncidentStatusClient) UpdateOne(_m *IncidentStatus) *IncidentStatusUpdateOne { + mutation := newIncidentStatusMutation(c.config, OpUpdateOne, withIncidentStatus(_m)) + return &IncidentStatusUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *IncidentStatusClient) UpdateOneID(id int) *IncidentStatusUpdateOne { + mutation := newIncidentStatusMutation(c.config, OpUpdateOne, withIncidentStatusID(id)) + return &IncidentStatusUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for IncidentStatus. +func (c *IncidentStatusClient) Delete() *IncidentStatusDelete { + mutation := newIncidentStatusMutation(c.config, OpDelete) + return &IncidentStatusDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *IncidentStatusClient) DeleteOne(_m *IncidentStatus) *IncidentStatusDeleteOne { + return c.DeleteOneID(_m.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *IncidentStatusClient) DeleteOneID(id int) *IncidentStatusDeleteOne { + builder := c.Delete().Where(incidentstatus.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &IncidentStatusDeleteOne{builder} +} + +// Query returns a query builder for IncidentStatus. +func (c *IncidentStatusClient) Query() *IncidentStatusQuery { + return &IncidentStatusQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeIncidentStatus}, + inters: c.Interceptors(), + } +} + +// Get returns a IncidentStatus entity by its id. +func (c *IncidentStatusClient) Get(ctx context.Context, id int) (*IncidentStatus, error) { + return c.Query().Where(incidentstatus.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *IncidentStatusClient) GetX(ctx context.Context, id int) *IncidentStatus { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *IncidentStatusClient) Hooks() []Hook { + return c.hooks.IncidentStatus +} + +// Interceptors returns the client interceptors. +func (c *IncidentStatusClient) Interceptors() []Interceptor { + return c.inters.IncidentStatus +} + +func (c *IncidentStatusClient) mutate(ctx context.Context, m *IncidentStatusMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&IncidentStatusCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&IncidentStatusUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&IncidentStatusUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&IncidentStatusDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown IncidentStatus mutation op: %q", m.Op()) + } +} + +// NotificationOutboxClient is a client for the NotificationOutbox schema. +type NotificationOutboxClient struct { + config +} + +// NewNotificationOutboxClient returns a client for the NotificationOutbox from the given config. +func NewNotificationOutboxClient(c config) *NotificationOutboxClient { + return &NotificationOutboxClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `notificationoutbox.Hooks(f(g(h())))`. +func (c *NotificationOutboxClient) Use(hooks ...Hook) { + c.hooks.NotificationOutbox = append(c.hooks.NotificationOutbox, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `notificationoutbox.Intercept(f(g(h())))`. +func (c *NotificationOutboxClient) Intercept(interceptors ...Interceptor) { + c.inters.NotificationOutbox = append(c.inters.NotificationOutbox, interceptors...) +} + +// Create returns a builder for creating a NotificationOutbox entity. +func (c *NotificationOutboxClient) Create() *NotificationOutboxCreate { + mutation := newNotificationOutboxMutation(c.config, OpCreate) + return &NotificationOutboxCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of NotificationOutbox entities. +func (c *NotificationOutboxClient) CreateBulk(builders ...*NotificationOutboxCreate) *NotificationOutboxCreateBulk { + return &NotificationOutboxCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *NotificationOutboxClient) MapCreateBulk(slice any, setFunc func(*NotificationOutboxCreate, int)) *NotificationOutboxCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &NotificationOutboxCreateBulk{err: fmt.Errorf("calling to NotificationOutboxClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*NotificationOutboxCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &NotificationOutboxCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for NotificationOutbox. +func (c *NotificationOutboxClient) Update() *NotificationOutboxUpdate { + mutation := newNotificationOutboxMutation(c.config, OpUpdate) + return &NotificationOutboxUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *NotificationOutboxClient) UpdateOne(_m *NotificationOutbox) *NotificationOutboxUpdateOne { + mutation := newNotificationOutboxMutation(c.config, OpUpdateOne, withNotificationOutbox(_m)) + return &NotificationOutboxUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *NotificationOutboxClient) UpdateOneID(id int) *NotificationOutboxUpdateOne { + mutation := newNotificationOutboxMutation(c.config, OpUpdateOne, withNotificationOutboxID(id)) + return &NotificationOutboxUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for NotificationOutbox. +func (c *NotificationOutboxClient) Delete() *NotificationOutboxDelete { + mutation := newNotificationOutboxMutation(c.config, OpDelete) + return &NotificationOutboxDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *NotificationOutboxClient) DeleteOne(_m *NotificationOutbox) *NotificationOutboxDeleteOne { + return c.DeleteOneID(_m.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *NotificationOutboxClient) DeleteOneID(id int) *NotificationOutboxDeleteOne { + builder := c.Delete().Where(notificationoutbox.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &NotificationOutboxDeleteOne{builder} +} + +// Query returns a query builder for NotificationOutbox. +func (c *NotificationOutboxClient) Query() *NotificationOutboxQuery { + return &NotificationOutboxQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeNotificationOutbox}, + inters: c.Interceptors(), + } +} + +// Get returns a NotificationOutbox entity by its id. +func (c *NotificationOutboxClient) Get(ctx context.Context, id int) (*NotificationOutbox, error) { + return c.Query().Where(notificationoutbox.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *NotificationOutboxClient) GetX(ctx context.Context, id int) *NotificationOutbox { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryIncident queries the incident edge of a NotificationOutbox. +func (c *NotificationOutboxClient) QueryIncident(_m *NotificationOutbox) *IncidentQuery { + query := (&IncidentClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := _m.ID + step := sqlgraph.NewStep( + sqlgraph.From(notificationoutbox.Table, notificationoutbox.FieldID, id), + sqlgraph.To(incident.Table, incident.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, notificationoutbox.IncidentTable, notificationoutbox.IncidentColumn), + ) + fromV = sqlgraph.Neighbors(_m.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *NotificationOutboxClient) Hooks() []Hook { + return c.hooks.NotificationOutbox +} + +// Interceptors returns the client interceptors. +func (c *NotificationOutboxClient) Interceptors() []Interceptor { + return c.inters.NotificationOutbox +} + +func (c *NotificationOutboxClient) mutate(ctx context.Context, m *NotificationOutboxMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&NotificationOutboxCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&NotificationOutboxUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&NotificationOutboxUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&NotificationOutboxDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown NotificationOutbox mutation op: %q", m.Op()) + } +} + +// hooks and interceptors per client, for fast access. +type ( + hooks struct { + Component, ComponentAttr, Incident, IncidentStatus, + NotificationOutbox []ent.Hook + } + inters struct { + Component, ComponentAttr, Incident, IncidentStatus, + NotificationOutbox []ent.Interceptor + } +) diff --git a/ent/component.go b/ent/component.go new file mode 100644 index 0000000..6920430 --- /dev/null +++ b/ent/component.go @@ -0,0 +1,181 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/stackmon/otc-status-dashboard/ent/component" +) + +// Component is the model entity for the Component schema. +type Component struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Name holds the value of the "name" field. + Name string `json:"name,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // ModifiedAt holds the value of the "modified_at" field. + ModifiedAt time.Time `json:"modified_at,omitempty"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt time.Time `json:"deleted_at,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the ComponentQuery when eager-loading is set. + Edges ComponentEdges `json:"edges"` + selectValues sql.SelectValues +} + +// ComponentEdges holds the relations/edges for other nodes in the graph. +type ComponentEdges struct { + // Attributes holds the value of the attributes edge. + Attributes []*ComponentAttr `json:"attributes,omitempty"` + // Incidents holds the value of the incidents edge. + Incidents []*Incident `json:"incidents,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [2]bool +} + +// AttributesOrErr returns the Attributes value or an error if the edge +// was not loaded in eager-loading. +func (e ComponentEdges) AttributesOrErr() ([]*ComponentAttr, error) { + if e.loadedTypes[0] { + return e.Attributes, nil + } + return nil, &NotLoadedError{edge: "attributes"} +} + +// IncidentsOrErr returns the Incidents value or an error if the edge +// was not loaded in eager-loading. +func (e ComponentEdges) IncidentsOrErr() ([]*Incident, error) { + if e.loadedTypes[1] { + return e.Incidents, nil + } + return nil, &NotLoadedError{edge: "incidents"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Component) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case component.FieldID: + values[i] = new(sql.NullInt64) + case component.FieldName: + values[i] = new(sql.NullString) + case component.FieldCreatedAt, component.FieldModifiedAt, component.FieldDeletedAt: + values[i] = new(sql.NullTime) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Component fields. +func (_m *Component) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case component.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + _m.ID = int(value.Int64) + case component.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + _m.Name = value.String + } + case component.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + _m.CreatedAt = value.Time + } + case component.FieldModifiedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field modified_at", values[i]) + } else if value.Valid { + _m.ModifiedAt = value.Time + } + case component.FieldDeletedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value.Valid { + _m.DeletedAt = value.Time + } + default: + _m.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the Component. +// This includes values selected through modifiers, order, etc. +func (_m *Component) Value(name string) (ent.Value, error) { + return _m.selectValues.Get(name) +} + +// QueryAttributes queries the "attributes" edge of the Component entity. +func (_m *Component) QueryAttributes() *ComponentAttrQuery { + return NewComponentClient(_m.config).QueryAttributes(_m) +} + +// QueryIncidents queries the "incidents" edge of the Component entity. +func (_m *Component) QueryIncidents() *IncidentQuery { + return NewComponentClient(_m.config).QueryIncidents(_m) +} + +// Update returns a builder for updating this Component. +// Note that you need to call Component.Unwrap() before calling this method if this Component +// was returned from a transaction, and the transaction was committed or rolled back. +func (_m *Component) Update() *ComponentUpdateOne { + return NewComponentClient(_m.config).UpdateOne(_m) +} + +// Unwrap unwraps the Component entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (_m *Component) Unwrap() *Component { + _tx, ok := _m.config.driver.(*txDriver) + if !ok { + panic("ent: Component is not a transactional entity") + } + _m.config.driver = _tx.drv + return _m +} + +// String implements the fmt.Stringer. +func (_m *Component) String() string { + var builder strings.Builder + builder.WriteString("Component(") + builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID)) + builder.WriteString("name=") + builder.WriteString(_m.Name) + builder.WriteString(", ") + builder.WriteString("created_at=") + builder.WriteString(_m.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("modified_at=") + builder.WriteString(_m.ModifiedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("deleted_at=") + builder.WriteString(_m.DeletedAt.Format(time.ANSIC)) + builder.WriteByte(')') + return builder.String() +} + +// Components is a parsable slice of Component. +type Components []*Component diff --git a/ent/component/component.go b/ent/component/component.go new file mode 100644 index 0000000..e8ef3e6 --- /dev/null +++ b/ent/component/component.go @@ -0,0 +1,141 @@ +// Code generated by ent, DO NOT EDIT. + +package component + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the component type in the database. + Label = "component" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldModifiedAt holds the string denoting the modified_at field in the database. + FieldModifiedAt = "modified_at" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // EdgeAttributes holds the string denoting the attributes edge name in mutations. + EdgeAttributes = "attributes" + // EdgeIncidents holds the string denoting the incidents edge name in mutations. + EdgeIncidents = "incidents" + // Table holds the table name of the component in the database. + Table = "component" + // AttributesTable is the table that holds the attributes relation/edge. + AttributesTable = "component_attribute" + // AttributesInverseTable is the table name for the ComponentAttr entity. + // It exists in this package in order to avoid circular dependency with the "componentattr" package. + AttributesInverseTable = "component_attribute" + // AttributesColumn is the table column denoting the attributes relation/edge. + AttributesColumn = "component_id" + // IncidentsTable is the table that holds the incidents relation/edge. The primary key declared below. + IncidentsTable = "incident_component_relation" + // IncidentsInverseTable is the table name for the Incident entity. + // It exists in this package in order to avoid circular dependency with the "incident" package. + IncidentsInverseTable = "incident" +) + +// Columns holds all SQL columns for component fields. +var Columns = []string{ + FieldID, + FieldName, + FieldCreatedAt, + FieldModifiedAt, + FieldDeletedAt, +} + +var ( + // IncidentsPrimaryKey and IncidentsColumn2 are the table columns denoting the + // primary key for the incidents relation (M2M). + IncidentsPrimaryKey = []string{"incident_id", "component_id"} +) + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error +) + +// OrderOption defines the ordering options for the Component queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByModifiedAt orders the results by the modified_at field. +func ByModifiedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldModifiedAt, opts...).ToFunc() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByAttributesCount orders the results by attributes count. +func ByAttributesCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newAttributesStep(), opts...) + } +} + +// ByAttributes orders the results by attributes terms. +func ByAttributes(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newAttributesStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} + +// ByIncidentsCount orders the results by incidents count. +func ByIncidentsCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newIncidentsStep(), opts...) + } +} + +// ByIncidents orders the results by incidents terms. +func ByIncidents(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newIncidentsStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} +func newAttributesStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(AttributesInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, AttributesTable, AttributesColumn), + ) +} +func newIncidentsStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(IncidentsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, IncidentsTable, IncidentsPrimaryKey...), + ) +} diff --git a/ent/component/where.go b/ent/component/where.go new file mode 100644 index 0000000..bb45807 --- /dev/null +++ b/ent/component/where.go @@ -0,0 +1,352 @@ +// Code generated by ent, DO NOT EDIT. + +package component + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.Component { + return predicate.Component(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.Component { + return predicate.Component(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.Component { + return predicate.Component(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.Component { + return predicate.Component(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.Component { + return predicate.Component(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.Component { + return predicate.Component(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.Component { + return predicate.Component(sql.FieldLTE(FieldID, id)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldName, v)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldCreatedAt, v)) +} + +// ModifiedAt applies equality check predicate on the "modified_at" field. It's identical to ModifiedAtEQ. +func ModifiedAt(v time.Time) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldModifiedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v time.Time) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldDeletedAt, v)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.Component { + return predicate.Component(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.Component { + return predicate.Component(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.Component { + return predicate.Component(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.Component { + return predicate.Component(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.Component { + return predicate.Component(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.Component { + return predicate.Component(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.Component { + return predicate.Component(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.Component { + return predicate.Component(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.Component { + return predicate.Component(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.Component { + return predicate.Component(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.Component { + return predicate.Component(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.Component { + return predicate.Component(sql.FieldContainsFold(FieldName, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.Component { + return predicate.Component(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.Component { + return predicate.Component(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.Component { + return predicate.Component(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.Component { + return predicate.Component(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.Component { + return predicate.Component(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.Component { + return predicate.Component(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.Component { + return predicate.Component(sql.FieldLTE(FieldCreatedAt, v)) +} + +// CreatedAtIsNil applies the IsNil predicate on the "created_at" field. +func CreatedAtIsNil() predicate.Component { + return predicate.Component(sql.FieldIsNull(FieldCreatedAt)) +} + +// CreatedAtNotNil applies the NotNil predicate on the "created_at" field. +func CreatedAtNotNil() predicate.Component { + return predicate.Component(sql.FieldNotNull(FieldCreatedAt)) +} + +// ModifiedAtEQ applies the EQ predicate on the "modified_at" field. +func ModifiedAtEQ(v time.Time) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldModifiedAt, v)) +} + +// ModifiedAtNEQ applies the NEQ predicate on the "modified_at" field. +func ModifiedAtNEQ(v time.Time) predicate.Component { + return predicate.Component(sql.FieldNEQ(FieldModifiedAt, v)) +} + +// ModifiedAtIn applies the In predicate on the "modified_at" field. +func ModifiedAtIn(vs ...time.Time) predicate.Component { + return predicate.Component(sql.FieldIn(FieldModifiedAt, vs...)) +} + +// ModifiedAtNotIn applies the NotIn predicate on the "modified_at" field. +func ModifiedAtNotIn(vs ...time.Time) predicate.Component { + return predicate.Component(sql.FieldNotIn(FieldModifiedAt, vs...)) +} + +// ModifiedAtGT applies the GT predicate on the "modified_at" field. +func ModifiedAtGT(v time.Time) predicate.Component { + return predicate.Component(sql.FieldGT(FieldModifiedAt, v)) +} + +// ModifiedAtGTE applies the GTE predicate on the "modified_at" field. +func ModifiedAtGTE(v time.Time) predicate.Component { + return predicate.Component(sql.FieldGTE(FieldModifiedAt, v)) +} + +// ModifiedAtLT applies the LT predicate on the "modified_at" field. +func ModifiedAtLT(v time.Time) predicate.Component { + return predicate.Component(sql.FieldLT(FieldModifiedAt, v)) +} + +// ModifiedAtLTE applies the LTE predicate on the "modified_at" field. +func ModifiedAtLTE(v time.Time) predicate.Component { + return predicate.Component(sql.FieldLTE(FieldModifiedAt, v)) +} + +// ModifiedAtIsNil applies the IsNil predicate on the "modified_at" field. +func ModifiedAtIsNil() predicate.Component { + return predicate.Component(sql.FieldIsNull(FieldModifiedAt)) +} + +// ModifiedAtNotNil applies the NotNil predicate on the "modified_at" field. +func ModifiedAtNotNil() predicate.Component { + return predicate.Component(sql.FieldNotNull(FieldModifiedAt)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v time.Time) predicate.Component { + return predicate.Component(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v time.Time) predicate.Component { + return predicate.Component(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...time.Time) predicate.Component { + return predicate.Component(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...time.Time) predicate.Component { + return predicate.Component(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v time.Time) predicate.Component { + return predicate.Component(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v time.Time) predicate.Component { + return predicate.Component(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v time.Time) predicate.Component { + return predicate.Component(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v time.Time) predicate.Component { + return predicate.Component(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.Component { + return predicate.Component(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.Component { + return predicate.Component(sql.FieldNotNull(FieldDeletedAt)) +} + +// HasAttributes applies the HasEdge predicate on the "attributes" edge. +func HasAttributes() predicate.Component { + return predicate.Component(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, AttributesTable, AttributesColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasAttributesWith applies the HasEdge predicate on the "attributes" edge with a given conditions (other predicates). +func HasAttributesWith(preds ...predicate.ComponentAttr) predicate.Component { + return predicate.Component(func(s *sql.Selector) { + step := newAttributesStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasIncidents applies the HasEdge predicate on the "incidents" edge. +func HasIncidents() predicate.Component { + return predicate.Component(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, IncidentsTable, IncidentsPrimaryKey...), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasIncidentsWith applies the HasEdge predicate on the "incidents" edge with a given conditions (other predicates). +func HasIncidentsWith(preds ...predicate.Incident) predicate.Component { + return predicate.Component(func(s *sql.Selector) { + step := newIncidentsStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Component) predicate.Component { + return predicate.Component(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Component) predicate.Component { + return predicate.Component(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Component) predicate.Component { + return predicate.Component(sql.NotPredicates(p)) +} diff --git a/ent/component_create.go b/ent/component_create.go new file mode 100644 index 0000000..c0db3a1 --- /dev/null +++ b/ent/component_create.go @@ -0,0 +1,788 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/incident" +) + +// ComponentCreate is the builder for creating a Component entity. +type ComponentCreate struct { + config + mutation *ComponentMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetName sets the "name" field. +func (_c *ComponentCreate) SetName(v string) *ComponentCreate { + _c.mutation.SetName(v) + return _c +} + +// SetCreatedAt sets the "created_at" field. +func (_c *ComponentCreate) SetCreatedAt(v time.Time) *ComponentCreate { + _c.mutation.SetCreatedAt(v) + return _c +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_c *ComponentCreate) SetNillableCreatedAt(v *time.Time) *ComponentCreate { + if v != nil { + _c.SetCreatedAt(*v) + } + return _c +} + +// SetModifiedAt sets the "modified_at" field. +func (_c *ComponentCreate) SetModifiedAt(v time.Time) *ComponentCreate { + _c.mutation.SetModifiedAt(v) + return _c +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_c *ComponentCreate) SetNillableModifiedAt(v *time.Time) *ComponentCreate { + if v != nil { + _c.SetModifiedAt(*v) + } + return _c +} + +// SetDeletedAt sets the "deleted_at" field. +func (_c *ComponentCreate) SetDeletedAt(v time.Time) *ComponentCreate { + _c.mutation.SetDeletedAt(v) + return _c +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_c *ComponentCreate) SetNillableDeletedAt(v *time.Time) *ComponentCreate { + if v != nil { + _c.SetDeletedAt(*v) + } + return _c +} + +// SetID sets the "id" field. +func (_c *ComponentCreate) SetID(v int) *ComponentCreate { + _c.mutation.SetID(v) + return _c +} + +// AddAttributeIDs adds the "attributes" edge to the ComponentAttr entity by IDs. +func (_c *ComponentCreate) AddAttributeIDs(ids ...int) *ComponentCreate { + _c.mutation.AddAttributeIDs(ids...) + return _c +} + +// AddAttributes adds the "attributes" edges to the ComponentAttr entity. +func (_c *ComponentCreate) AddAttributes(v ...*ComponentAttr) *ComponentCreate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _c.AddAttributeIDs(ids...) +} + +// AddIncidentIDs adds the "incidents" edge to the Incident entity by IDs. +func (_c *ComponentCreate) AddIncidentIDs(ids ...int) *ComponentCreate { + _c.mutation.AddIncidentIDs(ids...) + return _c +} + +// AddIncidents adds the "incidents" edges to the Incident entity. +func (_c *ComponentCreate) AddIncidents(v ...*Incident) *ComponentCreate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _c.AddIncidentIDs(ids...) +} + +// Mutation returns the ComponentMutation object of the builder. +func (_c *ComponentCreate) Mutation() *ComponentMutation { + return _c.mutation +} + +// Save creates the Component in the database. +func (_c *ComponentCreate) Save(ctx context.Context) (*Component, error) { + return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (_c *ComponentCreate) SaveX(ctx context.Context) *Component { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *ComponentCreate) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *ComponentCreate) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_c *ComponentCreate) check() error { + if _, ok := _c.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Component.name"`)} + } + if v, ok := _c.mutation.Name(); ok { + if err := component.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Component.name": %w`, err)} + } + } + return nil +} + +func (_c *ComponentCreate) sqlSave(ctx context.Context) (*Component, error) { + if err := _c.check(); err != nil { + return nil, err + } + _node, _spec := _c.createSpec() + if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int(id) + } + _c.mutation.id = &_node.ID + _c.mutation.done = true + return _node, nil +} + +func (_c *ComponentCreate) createSpec() (*Component, *sqlgraph.CreateSpec) { + var ( + _node = &Component{config: _c.config} + _spec = sqlgraph.NewCreateSpec(component.Table, sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt)) + ) + _spec.OnConflict = _c.conflict + if id, ok := _c.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := _c.mutation.Name(); ok { + _spec.SetField(component.FieldName, field.TypeString, value) + _node.Name = value + } + if value, ok := _c.mutation.CreatedAt(); ok { + _spec.SetField(component.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := _c.mutation.ModifiedAt(); ok { + _spec.SetField(component.FieldModifiedAt, field.TypeTime, value) + _node.ModifiedAt = value + } + if value, ok := _c.mutation.DeletedAt(); ok { + _spec.SetField(component.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = value + } + if nodes := _c.mutation.AttributesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: component.AttributesTable, + Columns: []string{component.AttributesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := _c.mutation.IncidentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: component.IncidentsTable, + Columns: component.IncidentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.Component.Create(). +// SetName(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.ComponentUpsert) { +// SetName(v+v). +// }). +// Exec(ctx) +func (_c *ComponentCreate) OnConflict(opts ...sql.ConflictOption) *ComponentUpsertOne { + _c.conflict = opts + return &ComponentUpsertOne{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.Component.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *ComponentCreate) OnConflictColumns(columns ...string) *ComponentUpsertOne { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &ComponentUpsertOne{ + create: _c, + } +} + +type ( + // ComponentUpsertOne is the builder for "upsert"-ing + // one Component node. + ComponentUpsertOne struct { + create *ComponentCreate + } + + // ComponentUpsert is the "OnConflict" setter. + ComponentUpsert struct { + *sql.UpdateSet + } +) + +// SetName sets the "name" field. +func (u *ComponentUpsert) SetName(v string) *ComponentUpsert { + u.Set(component.FieldName, v) + return u +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ComponentUpsert) UpdateName() *ComponentUpsert { + u.SetExcluded(component.FieldName) + return u +} + +// SetCreatedAt sets the "created_at" field. +func (u *ComponentUpsert) SetCreatedAt(v time.Time) *ComponentUpsert { + u.Set(component.FieldCreatedAt, v) + return u +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *ComponentUpsert) UpdateCreatedAt() *ComponentUpsert { + u.SetExcluded(component.FieldCreatedAt) + return u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *ComponentUpsert) ClearCreatedAt() *ComponentUpsert { + u.SetNull(component.FieldCreatedAt) + return u +} + +// SetModifiedAt sets the "modified_at" field. +func (u *ComponentUpsert) SetModifiedAt(v time.Time) *ComponentUpsert { + u.Set(component.FieldModifiedAt, v) + return u +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *ComponentUpsert) UpdateModifiedAt() *ComponentUpsert { + u.SetExcluded(component.FieldModifiedAt) + return u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *ComponentUpsert) ClearModifiedAt() *ComponentUpsert { + u.SetNull(component.FieldModifiedAt) + return u +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *ComponentUpsert) SetDeletedAt(v time.Time) *ComponentUpsert { + u.Set(component.FieldDeletedAt, v) + return u +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *ComponentUpsert) UpdateDeletedAt() *ComponentUpsert { + u.SetExcluded(component.FieldDeletedAt) + return u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *ComponentUpsert) ClearDeletedAt() *ComponentUpsert { + u.SetNull(component.FieldDeletedAt) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. +// Using this option is equivalent to using: +// +// client.Component.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(component.FieldID) +// }), +// ). +// Exec(ctx) +func (u *ComponentUpsertOne) UpdateNewValues() *ComponentUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.ID(); exists { + s.SetIgnore(component.FieldID) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.Component.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *ComponentUpsertOne) Ignore() *ComponentUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *ComponentUpsertOne) DoNothing() *ComponentUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the ComponentCreate.OnConflict +// documentation for more info. +func (u *ComponentUpsertOne) Update(set func(*ComponentUpsert)) *ComponentUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&ComponentUpsert{UpdateSet: update}) + })) + return u +} + +// SetName sets the "name" field. +func (u *ComponentUpsertOne) SetName(v string) *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.SetName(v) + }) +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ComponentUpsertOne) UpdateName() *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.UpdateName() + }) +} + +// SetCreatedAt sets the "created_at" field. +func (u *ComponentUpsertOne) SetCreatedAt(v time.Time) *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *ComponentUpsertOne) UpdateCreatedAt() *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.UpdateCreatedAt() + }) +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *ComponentUpsertOne) ClearCreatedAt() *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.ClearCreatedAt() + }) +} + +// SetModifiedAt sets the "modified_at" field. +func (u *ComponentUpsertOne) SetModifiedAt(v time.Time) *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.SetModifiedAt(v) + }) +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *ComponentUpsertOne) UpdateModifiedAt() *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.UpdateModifiedAt() + }) +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *ComponentUpsertOne) ClearModifiedAt() *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.ClearModifiedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *ComponentUpsertOne) SetDeletedAt(v time.Time) *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *ComponentUpsertOne) UpdateDeletedAt() *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *ComponentUpsertOne) ClearDeletedAt() *ComponentUpsertOne { + return u.Update(func(s *ComponentUpsert) { + s.ClearDeletedAt() + }) +} + +// Exec executes the query. +func (u *ComponentUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for ComponentCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *ComponentUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *ComponentUpsertOne) ID(ctx context.Context) (id int, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *ComponentUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// ComponentCreateBulk is the builder for creating many Component entities in bulk. +type ComponentCreateBulk struct { + config + err error + builders []*ComponentCreate + conflict []sql.ConflictOption +} + +// Save creates the Component entities in the database. +func (_c *ComponentCreateBulk) Save(ctx context.Context) ([]*Component, error) { + if _c.err != nil { + return nil, _c.err + } + specs := make([]*sqlgraph.CreateSpec, len(_c.builders)) + nodes := make([]*Component, len(_c.builders)) + mutators := make([]Mutator, len(_c.builders)) + for i := range _c.builders { + func(i int, root context.Context) { + builder := _c.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ComponentMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = _c.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (_c *ComponentCreateBulk) SaveX(ctx context.Context) []*Component { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *ComponentCreateBulk) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *ComponentCreateBulk) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.Component.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.ComponentUpsert) { +// SetName(v+v). +// }). +// Exec(ctx) +func (_c *ComponentCreateBulk) OnConflict(opts ...sql.ConflictOption) *ComponentUpsertBulk { + _c.conflict = opts + return &ComponentUpsertBulk{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.Component.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *ComponentCreateBulk) OnConflictColumns(columns ...string) *ComponentUpsertBulk { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &ComponentUpsertBulk{ + create: _c, + } +} + +// ComponentUpsertBulk is the builder for "upsert"-ing +// a bulk of Component nodes. +type ComponentUpsertBulk struct { + create *ComponentCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.Component.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(component.FieldID) +// }), +// ). +// Exec(ctx) +func (u *ComponentUpsertBulk) UpdateNewValues() *ComponentUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.ID(); exists { + s.SetIgnore(component.FieldID) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.Component.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *ComponentUpsertBulk) Ignore() *ComponentUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *ComponentUpsertBulk) DoNothing() *ComponentUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the ComponentCreateBulk.OnConflict +// documentation for more info. +func (u *ComponentUpsertBulk) Update(set func(*ComponentUpsert)) *ComponentUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&ComponentUpsert{UpdateSet: update}) + })) + return u +} + +// SetName sets the "name" field. +func (u *ComponentUpsertBulk) SetName(v string) *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.SetName(v) + }) +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ComponentUpsertBulk) UpdateName() *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.UpdateName() + }) +} + +// SetCreatedAt sets the "created_at" field. +func (u *ComponentUpsertBulk) SetCreatedAt(v time.Time) *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *ComponentUpsertBulk) UpdateCreatedAt() *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.UpdateCreatedAt() + }) +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *ComponentUpsertBulk) ClearCreatedAt() *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.ClearCreatedAt() + }) +} + +// SetModifiedAt sets the "modified_at" field. +func (u *ComponentUpsertBulk) SetModifiedAt(v time.Time) *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.SetModifiedAt(v) + }) +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *ComponentUpsertBulk) UpdateModifiedAt() *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.UpdateModifiedAt() + }) +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *ComponentUpsertBulk) ClearModifiedAt() *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.ClearModifiedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *ComponentUpsertBulk) SetDeletedAt(v time.Time) *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *ComponentUpsertBulk) UpdateDeletedAt() *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *ComponentUpsertBulk) ClearDeletedAt() *ComponentUpsertBulk { + return u.Update(func(s *ComponentUpsert) { + s.ClearDeletedAt() + }) +} + +// Exec executes the query. +func (u *ComponentUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ComponentCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for ComponentCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *ComponentUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/component_delete.go b/ent/component_delete.go new file mode 100644 index 0000000..2976bd4 --- /dev/null +++ b/ent/component_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ComponentDelete is the builder for deleting a Component entity. +type ComponentDelete struct { + config + hooks []Hook + mutation *ComponentMutation +} + +// Where appends a list predicates to the ComponentDelete builder. +func (_d *ComponentDelete) Where(ps ...predicate.Component) *ComponentDelete { + _d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (_d *ComponentDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *ComponentDelete) ExecX(ctx context.Context) int { + n, err := _d.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (_d *ComponentDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(component.Table, sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt)) + if ps := _d.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + _d.mutation.done = true + return affected, err +} + +// ComponentDeleteOne is the builder for deleting a single Component entity. +type ComponentDeleteOne struct { + _d *ComponentDelete +} + +// Where appends a list predicates to the ComponentDelete builder. +func (_d *ComponentDeleteOne) Where(ps ...predicate.Component) *ComponentDeleteOne { + _d._d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query. +func (_d *ComponentDeleteOne) Exec(ctx context.Context) error { + n, err := _d._d.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{component.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *ComponentDeleteOne) ExecX(ctx context.Context) { + if err := _d.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/component_query.go b/ent/component_query.go new file mode 100644 index 0000000..0dbf193 --- /dev/null +++ b/ent/component_query.go @@ -0,0 +1,711 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ComponentQuery is the builder for querying Component entities. +type ComponentQuery struct { + config + ctx *QueryContext + order []component.OrderOption + inters []Interceptor + predicates []predicate.Component + withAttributes *ComponentAttrQuery + withIncidents *IncidentQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the ComponentQuery builder. +func (_q *ComponentQuery) Where(ps ...predicate.Component) *ComponentQuery { + _q.predicates = append(_q.predicates, ps...) + return _q +} + +// Limit the number of records to be returned by this query. +func (_q *ComponentQuery) Limit(limit int) *ComponentQuery { + _q.ctx.Limit = &limit + return _q +} + +// Offset to start from. +func (_q *ComponentQuery) Offset(offset int) *ComponentQuery { + _q.ctx.Offset = &offset + return _q +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (_q *ComponentQuery) Unique(unique bool) *ComponentQuery { + _q.ctx.Unique = &unique + return _q +} + +// Order specifies how the records should be ordered. +func (_q *ComponentQuery) Order(o ...component.OrderOption) *ComponentQuery { + _q.order = append(_q.order, o...) + return _q +} + +// QueryAttributes chains the current query on the "attributes" edge. +func (_q *ComponentQuery) QueryAttributes() *ComponentAttrQuery { + query := (&ComponentAttrClient{config: _q.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + selector := _q.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(component.Table, component.FieldID, selector), + sqlgraph.To(componentattr.Table, componentattr.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, component.AttributesTable, component.AttributesColumn), + ) + fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryIncidents chains the current query on the "incidents" edge. +func (_q *ComponentQuery) QueryIncidents() *IncidentQuery { + query := (&IncidentClient{config: _q.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + selector := _q.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(component.Table, component.FieldID, selector), + sqlgraph.To(incident.Table, incident.FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, component.IncidentsTable, component.IncidentsPrimaryKey...), + ) + fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first Component entity from the query. +// Returns a *NotFoundError when no Component was found. +func (_q *ComponentQuery) First(ctx context.Context) (*Component, error) { + nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{component.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (_q *ComponentQuery) FirstX(ctx context.Context) *Component { + node, err := _q.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Component ID from the query. +// Returns a *NotFoundError when no Component ID was found. +func (_q *ComponentQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{component.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (_q *ComponentQuery) FirstIDX(ctx context.Context) int { + id, err := _q.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Component entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one Component entity is found. +// Returns a *NotFoundError when no Component entities are found. +func (_q *ComponentQuery) Only(ctx context.Context) (*Component, error) { + nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{component.Label} + default: + return nil, &NotSingularError{component.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (_q *ComponentQuery) OnlyX(ctx context.Context) *Component { + node, err := _q.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Component ID in the query. +// Returns a *NotSingularError when more than one Component ID is found. +// Returns a *NotFoundError when no entities are found. +func (_q *ComponentQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{component.Label} + default: + err = &NotSingularError{component.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (_q *ComponentQuery) OnlyIDX(ctx context.Context) int { + id, err := _q.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Components. +func (_q *ComponentQuery) All(ctx context.Context) ([]*Component, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll) + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*Component, *ComponentQuery]() + return withInterceptors[[]*Component](ctx, _q, qr, _q.inters) +} + +// AllX is like All, but panics if an error occurs. +func (_q *ComponentQuery) AllX(ctx context.Context) []*Component { + nodes, err := _q.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Component IDs. +func (_q *ComponentQuery) IDs(ctx context.Context) (ids []int, err error) { + if _q.ctx.Unique == nil && _q.path != nil { + _q.Unique(true) + } + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs) + if err = _q.Select(component.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (_q *ComponentQuery) IDsX(ctx context.Context) []int { + ids, err := _q.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (_q *ComponentQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount) + if err := _q.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, _q, querierCount[*ComponentQuery](), _q.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (_q *ComponentQuery) CountX(ctx context.Context) int { + count, err := _q.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (_q *ComponentQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist) + switch _, err := _q.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (_q *ComponentQuery) ExistX(ctx context.Context) bool { + exist, err := _q.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the ComponentQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (_q *ComponentQuery) Clone() *ComponentQuery { + if _q == nil { + return nil + } + return &ComponentQuery{ + config: _q.config, + ctx: _q.ctx.Clone(), + order: append([]component.OrderOption{}, _q.order...), + inters: append([]Interceptor{}, _q.inters...), + predicates: append([]predicate.Component{}, _q.predicates...), + withAttributes: _q.withAttributes.Clone(), + withIncidents: _q.withIncidents.Clone(), + // clone intermediate query. + sql: _q.sql.Clone(), + path: _q.path, + } +} + +// WithAttributes tells the query-builder to eager-load the nodes that are connected to +// the "attributes" edge. The optional arguments are used to configure the query builder of the edge. +func (_q *ComponentQuery) WithAttributes(opts ...func(*ComponentAttrQuery)) *ComponentQuery { + query := (&ComponentAttrClient{config: _q.config}).Query() + for _, opt := range opts { + opt(query) + } + _q.withAttributes = query + return _q +} + +// WithIncidents tells the query-builder to eager-load the nodes that are connected to +// the "incidents" edge. The optional arguments are used to configure the query builder of the edge. +func (_q *ComponentQuery) WithIncidents(opts ...func(*IncidentQuery)) *ComponentQuery { + query := (&IncidentClient{config: _q.config}).Query() + for _, opt := range opts { + opt(query) + } + _q.withIncidents = query + return _q +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Name string `json:"name,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Component.Query(). +// GroupBy(component.FieldName). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (_q *ComponentQuery) GroupBy(field string, fields ...string) *ComponentGroupBy { + _q.ctx.Fields = append([]string{field}, fields...) + grbuild := &ComponentGroupBy{build: _q} + grbuild.flds = &_q.ctx.Fields + grbuild.label = component.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Name string `json:"name,omitempty"` +// } +// +// client.Component.Query(). +// Select(component.FieldName). +// Scan(ctx, &v) +func (_q *ComponentQuery) Select(fields ...string) *ComponentSelect { + _q.ctx.Fields = append(_q.ctx.Fields, fields...) + sbuild := &ComponentSelect{ComponentQuery: _q} + sbuild.label = component.Label + sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a ComponentSelect configured with the given aggregations. +func (_q *ComponentQuery) Aggregate(fns ...AggregateFunc) *ComponentSelect { + return _q.Select().Aggregate(fns...) +} + +func (_q *ComponentQuery) prepareQuery(ctx context.Context) error { + for _, inter := range _q.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, _q); err != nil { + return err + } + } + } + for _, f := range _q.ctx.Fields { + if !component.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if _q.path != nil { + prev, err := _q.path(ctx) + if err != nil { + return err + } + _q.sql = prev + } + return nil +} + +func (_q *ComponentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Component, error) { + var ( + nodes = []*Component{} + _spec = _q.querySpec() + loadedTypes = [2]bool{ + _q.withAttributes != nil, + _q.withIncidents != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*Component).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &Component{config: _q.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := _q.withAttributes; query != nil { + if err := _q.loadAttributes(ctx, query, nodes, + func(n *Component) { n.Edges.Attributes = []*ComponentAttr{} }, + func(n *Component, e *ComponentAttr) { n.Edges.Attributes = append(n.Edges.Attributes, e) }); err != nil { + return nil, err + } + } + if query := _q.withIncidents; query != nil { + if err := _q.loadIncidents(ctx, query, nodes, + func(n *Component) { n.Edges.Incidents = []*Incident{} }, + func(n *Component, e *Incident) { n.Edges.Incidents = append(n.Edges.Incidents, e) }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (_q *ComponentQuery) loadAttributes(ctx context.Context, query *ComponentAttrQuery, nodes []*Component, init func(*Component), assign func(*Component, *ComponentAttr)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*Component) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(componentattr.FieldComponentID) + } + query.Where(predicate.ComponentAttr(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(component.AttributesColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.ComponentID + node, ok := nodeids[fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "component_id" returned %v for node %v`, fk, n.ID) + } + assign(node, n) + } + return nil +} +func (_q *ComponentQuery) loadIncidents(ctx context.Context, query *IncidentQuery, nodes []*Component, init func(*Component), assign func(*Component, *Incident)) error { + edgeIDs := make([]driver.Value, len(nodes)) + byID := make(map[int]*Component) + nids := make(map[int]map[*Component]struct{}) + for i, node := range nodes { + edgeIDs[i] = node.ID + byID[node.ID] = node + if init != nil { + init(node) + } + } + query.Where(func(s *sql.Selector) { + joinT := sql.Table(component.IncidentsTable) + s.Join(joinT).On(s.C(incident.FieldID), joinT.C(component.IncidentsPrimaryKey[0])) + s.Where(sql.InValues(joinT.C(component.IncidentsPrimaryKey[1]), edgeIDs...)) + columns := s.SelectedColumns() + s.Select(joinT.C(component.IncidentsPrimaryKey[1])) + s.AppendSelect(columns...) + s.SetDistinct(false) + }) + if err := query.prepareQuery(ctx); err != nil { + return err + } + qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) { + return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) { + assign := spec.Assign + values := spec.ScanValues + spec.ScanValues = func(columns []string) ([]any, error) { + values, err := values(columns[1:]) + if err != nil { + return nil, err + } + return append([]any{new(sql.NullInt64)}, values...), nil + } + spec.Assign = func(columns []string, values []any) error { + outValue := int(values[0].(*sql.NullInt64).Int64) + inValue := int(values[1].(*sql.NullInt64).Int64) + if nids[inValue] == nil { + nids[inValue] = map[*Component]struct{}{byID[outValue]: {}} + return assign(columns[1:], values[1:]) + } + nids[inValue][byID[outValue]] = struct{}{} + return nil + } + }) + }) + neighbors, err := withInterceptors[[]*Incident](ctx, query, qr, query.inters) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nids[n.ID] + if !ok { + return fmt.Errorf(`unexpected "incidents" node returned %v`, n.ID) + } + for kn := range nodes { + assign(kn, n) + } + } + return nil +} + +func (_q *ComponentQuery) sqlCount(ctx context.Context) (int, error) { + _spec := _q.querySpec() + _spec.Node.Columns = _q.ctx.Fields + if len(_q.ctx.Fields) > 0 { + _spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique + } + return sqlgraph.CountNodes(ctx, _q.driver, _spec) +} + +func (_q *ComponentQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(component.Table, component.Columns, sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt)) + _spec.From = _q.sql + if unique := _q.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if _q.path != nil { + _spec.Unique = true + } + if fields := _q.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, component.FieldID) + for i := range fields { + if fields[i] != component.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := _q.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := _q.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := _q.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := _q.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (_q *ComponentQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(_q.driver.Dialect()) + t1 := builder.Table(component.Table) + columns := _q.ctx.Fields + if len(columns) == 0 { + columns = component.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if _q.sql != nil { + selector = _q.sql + selector.Select(selector.Columns(columns...)...) + } + if _q.ctx.Unique != nil && *_q.ctx.Unique { + selector.Distinct() + } + for _, p := range _q.predicates { + p(selector) + } + for _, p := range _q.order { + p(selector) + } + if offset := _q.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := _q.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ComponentGroupBy is the group-by builder for Component entities. +type ComponentGroupBy struct { + selector + build *ComponentQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (_g *ComponentGroupBy) Aggregate(fns ...AggregateFunc) *ComponentGroupBy { + _g.fns = append(_g.fns, fns...) + return _g +} + +// Scan applies the selector query and scans the result into the given value. +func (_g *ComponentGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy) + if err := _g.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*ComponentQuery, *ComponentGroupBy](ctx, _g.build, _g, _g.build.inters, v) +} + +func (_g *ComponentGroupBy) sqlScan(ctx context.Context, root *ComponentQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(_g.fns)) + for _, fn := range _g.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*_g.flds)+len(_g.fns)) + for _, f := range *_g.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*_g.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _g.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// ComponentSelect is the builder for selecting fields of Component entities. +type ComponentSelect struct { + *ComponentQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (_s *ComponentSelect) Aggregate(fns ...AggregateFunc) *ComponentSelect { + _s.fns = append(_s.fns, fns...) + return _s +} + +// Scan applies the selector query and scans the result into the given value. +func (_s *ComponentSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect) + if err := _s.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*ComponentQuery, *ComponentSelect](ctx, _s.ComponentQuery, _s, _s.inters, v) +} + +func (_s *ComponentSelect) sqlScan(ctx context.Context, root *ComponentQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(_s.fns)) + for _, fn := range _s.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*_s.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _s.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/component_update.go b/ent/component_update.go new file mode 100644 index 0000000..8417dbe --- /dev/null +++ b/ent/component_update.go @@ -0,0 +1,718 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ComponentUpdate is the builder for updating Component entities. +type ComponentUpdate struct { + config + hooks []Hook + mutation *ComponentMutation +} + +// Where appends a list predicates to the ComponentUpdate builder. +func (_u *ComponentUpdate) Where(ps ...predicate.Component) *ComponentUpdate { + _u.mutation.Where(ps...) + return _u +} + +// SetName sets the "name" field. +func (_u *ComponentUpdate) SetName(v string) *ComponentUpdate { + _u.mutation.SetName(v) + return _u +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (_u *ComponentUpdate) SetNillableName(v *string) *ComponentUpdate { + if v != nil { + _u.SetName(*v) + } + return _u +} + +// SetCreatedAt sets the "created_at" field. +func (_u *ComponentUpdate) SetCreatedAt(v time.Time) *ComponentUpdate { + _u.mutation.SetCreatedAt(v) + return _u +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_u *ComponentUpdate) SetNillableCreatedAt(v *time.Time) *ComponentUpdate { + if v != nil { + _u.SetCreatedAt(*v) + } + return _u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (_u *ComponentUpdate) ClearCreatedAt() *ComponentUpdate { + _u.mutation.ClearCreatedAt() + return _u +} + +// SetModifiedAt sets the "modified_at" field. +func (_u *ComponentUpdate) SetModifiedAt(v time.Time) *ComponentUpdate { + _u.mutation.SetModifiedAt(v) + return _u +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_u *ComponentUpdate) SetNillableModifiedAt(v *time.Time) *ComponentUpdate { + if v != nil { + _u.SetModifiedAt(*v) + } + return _u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (_u *ComponentUpdate) ClearModifiedAt() *ComponentUpdate { + _u.mutation.ClearModifiedAt() + return _u +} + +// SetDeletedAt sets the "deleted_at" field. +func (_u *ComponentUpdate) SetDeletedAt(v time.Time) *ComponentUpdate { + _u.mutation.SetDeletedAt(v) + return _u +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_u *ComponentUpdate) SetNillableDeletedAt(v *time.Time) *ComponentUpdate { + if v != nil { + _u.SetDeletedAt(*v) + } + return _u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (_u *ComponentUpdate) ClearDeletedAt() *ComponentUpdate { + _u.mutation.ClearDeletedAt() + return _u +} + +// AddAttributeIDs adds the "attributes" edge to the ComponentAttr entity by IDs. +func (_u *ComponentUpdate) AddAttributeIDs(ids ...int) *ComponentUpdate { + _u.mutation.AddAttributeIDs(ids...) + return _u +} + +// AddAttributes adds the "attributes" edges to the ComponentAttr entity. +func (_u *ComponentUpdate) AddAttributes(v ...*ComponentAttr) *ComponentUpdate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.AddAttributeIDs(ids...) +} + +// AddIncidentIDs adds the "incidents" edge to the Incident entity by IDs. +func (_u *ComponentUpdate) AddIncidentIDs(ids ...int) *ComponentUpdate { + _u.mutation.AddIncidentIDs(ids...) + return _u +} + +// AddIncidents adds the "incidents" edges to the Incident entity. +func (_u *ComponentUpdate) AddIncidents(v ...*Incident) *ComponentUpdate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.AddIncidentIDs(ids...) +} + +// Mutation returns the ComponentMutation object of the builder. +func (_u *ComponentUpdate) Mutation() *ComponentMutation { + return _u.mutation +} + +// ClearAttributes clears all "attributes" edges to the ComponentAttr entity. +func (_u *ComponentUpdate) ClearAttributes() *ComponentUpdate { + _u.mutation.ClearAttributes() + return _u +} + +// RemoveAttributeIDs removes the "attributes" edge to ComponentAttr entities by IDs. +func (_u *ComponentUpdate) RemoveAttributeIDs(ids ...int) *ComponentUpdate { + _u.mutation.RemoveAttributeIDs(ids...) + return _u +} + +// RemoveAttributes removes "attributes" edges to ComponentAttr entities. +func (_u *ComponentUpdate) RemoveAttributes(v ...*ComponentAttr) *ComponentUpdate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.RemoveAttributeIDs(ids...) +} + +// ClearIncidents clears all "incidents" edges to the Incident entity. +func (_u *ComponentUpdate) ClearIncidents() *ComponentUpdate { + _u.mutation.ClearIncidents() + return _u +} + +// RemoveIncidentIDs removes the "incidents" edge to Incident entities by IDs. +func (_u *ComponentUpdate) RemoveIncidentIDs(ids ...int) *ComponentUpdate { + _u.mutation.RemoveIncidentIDs(ids...) + return _u +} + +// RemoveIncidents removes "incidents" edges to Incident entities. +func (_u *ComponentUpdate) RemoveIncidents(v ...*Incident) *ComponentUpdate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.RemoveIncidentIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (_u *ComponentUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *ComponentUpdate) SaveX(ctx context.Context) int { + affected, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (_u *ComponentUpdate) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *ComponentUpdate) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *ComponentUpdate) check() error { + if v, ok := _u.mutation.Name(); ok { + if err := component.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Component.name": %w`, err)} + } + } + return nil +} + +func (_u *ComponentUpdate) sqlSave(ctx context.Context) (_node int, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(component.Table, component.Columns, sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt)) + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.Name(); ok { + _spec.SetField(component.FieldName, field.TypeString, value) + } + if value, ok := _u.mutation.CreatedAt(); ok { + _spec.SetField(component.FieldCreatedAt, field.TypeTime, value) + } + if _u.mutation.CreatedAtCleared() { + _spec.ClearField(component.FieldCreatedAt, field.TypeTime) + } + if value, ok := _u.mutation.ModifiedAt(); ok { + _spec.SetField(component.FieldModifiedAt, field.TypeTime, value) + } + if _u.mutation.ModifiedAtCleared() { + _spec.ClearField(component.FieldModifiedAt, field.TypeTime) + } + if value, ok := _u.mutation.DeletedAt(); ok { + _spec.SetField(component.FieldDeletedAt, field.TypeTime, value) + } + if _u.mutation.DeletedAtCleared() { + _spec.ClearField(component.FieldDeletedAt, field.TypeTime) + } + if _u.mutation.AttributesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: component.AttributesTable, + Columns: []string{component.AttributesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.RemovedAttributesIDs(); len(nodes) > 0 && !_u.mutation.AttributesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: component.AttributesTable, + Columns: []string{component.AttributesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.AttributesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: component.AttributesTable, + Columns: []string{component.AttributesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _u.mutation.IncidentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: component.IncidentsTable, + Columns: component.IncidentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.RemovedIncidentsIDs(); len(nodes) > 0 && !_u.mutation.IncidentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: component.IncidentsTable, + Columns: component.IncidentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.IncidentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: component.IncidentsTable, + Columns: component.IncidentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{component.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + _u.mutation.done = true + return _node, nil +} + +// ComponentUpdateOne is the builder for updating a single Component entity. +type ComponentUpdateOne struct { + config + fields []string + hooks []Hook + mutation *ComponentMutation +} + +// SetName sets the "name" field. +func (_u *ComponentUpdateOne) SetName(v string) *ComponentUpdateOne { + _u.mutation.SetName(v) + return _u +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (_u *ComponentUpdateOne) SetNillableName(v *string) *ComponentUpdateOne { + if v != nil { + _u.SetName(*v) + } + return _u +} + +// SetCreatedAt sets the "created_at" field. +func (_u *ComponentUpdateOne) SetCreatedAt(v time.Time) *ComponentUpdateOne { + _u.mutation.SetCreatedAt(v) + return _u +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_u *ComponentUpdateOne) SetNillableCreatedAt(v *time.Time) *ComponentUpdateOne { + if v != nil { + _u.SetCreatedAt(*v) + } + return _u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (_u *ComponentUpdateOne) ClearCreatedAt() *ComponentUpdateOne { + _u.mutation.ClearCreatedAt() + return _u +} + +// SetModifiedAt sets the "modified_at" field. +func (_u *ComponentUpdateOne) SetModifiedAt(v time.Time) *ComponentUpdateOne { + _u.mutation.SetModifiedAt(v) + return _u +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_u *ComponentUpdateOne) SetNillableModifiedAt(v *time.Time) *ComponentUpdateOne { + if v != nil { + _u.SetModifiedAt(*v) + } + return _u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (_u *ComponentUpdateOne) ClearModifiedAt() *ComponentUpdateOne { + _u.mutation.ClearModifiedAt() + return _u +} + +// SetDeletedAt sets the "deleted_at" field. +func (_u *ComponentUpdateOne) SetDeletedAt(v time.Time) *ComponentUpdateOne { + _u.mutation.SetDeletedAt(v) + return _u +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_u *ComponentUpdateOne) SetNillableDeletedAt(v *time.Time) *ComponentUpdateOne { + if v != nil { + _u.SetDeletedAt(*v) + } + return _u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (_u *ComponentUpdateOne) ClearDeletedAt() *ComponentUpdateOne { + _u.mutation.ClearDeletedAt() + return _u +} + +// AddAttributeIDs adds the "attributes" edge to the ComponentAttr entity by IDs. +func (_u *ComponentUpdateOne) AddAttributeIDs(ids ...int) *ComponentUpdateOne { + _u.mutation.AddAttributeIDs(ids...) + return _u +} + +// AddAttributes adds the "attributes" edges to the ComponentAttr entity. +func (_u *ComponentUpdateOne) AddAttributes(v ...*ComponentAttr) *ComponentUpdateOne { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.AddAttributeIDs(ids...) +} + +// AddIncidentIDs adds the "incidents" edge to the Incident entity by IDs. +func (_u *ComponentUpdateOne) AddIncidentIDs(ids ...int) *ComponentUpdateOne { + _u.mutation.AddIncidentIDs(ids...) + return _u +} + +// AddIncidents adds the "incidents" edges to the Incident entity. +func (_u *ComponentUpdateOne) AddIncidents(v ...*Incident) *ComponentUpdateOne { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.AddIncidentIDs(ids...) +} + +// Mutation returns the ComponentMutation object of the builder. +func (_u *ComponentUpdateOne) Mutation() *ComponentMutation { + return _u.mutation +} + +// ClearAttributes clears all "attributes" edges to the ComponentAttr entity. +func (_u *ComponentUpdateOne) ClearAttributes() *ComponentUpdateOne { + _u.mutation.ClearAttributes() + return _u +} + +// RemoveAttributeIDs removes the "attributes" edge to ComponentAttr entities by IDs. +func (_u *ComponentUpdateOne) RemoveAttributeIDs(ids ...int) *ComponentUpdateOne { + _u.mutation.RemoveAttributeIDs(ids...) + return _u +} + +// RemoveAttributes removes "attributes" edges to ComponentAttr entities. +func (_u *ComponentUpdateOne) RemoveAttributes(v ...*ComponentAttr) *ComponentUpdateOne { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.RemoveAttributeIDs(ids...) +} + +// ClearIncidents clears all "incidents" edges to the Incident entity. +func (_u *ComponentUpdateOne) ClearIncidents() *ComponentUpdateOne { + _u.mutation.ClearIncidents() + return _u +} + +// RemoveIncidentIDs removes the "incidents" edge to Incident entities by IDs. +func (_u *ComponentUpdateOne) RemoveIncidentIDs(ids ...int) *ComponentUpdateOne { + _u.mutation.RemoveIncidentIDs(ids...) + return _u +} + +// RemoveIncidents removes "incidents" edges to Incident entities. +func (_u *ComponentUpdateOne) RemoveIncidents(v ...*Incident) *ComponentUpdateOne { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.RemoveIncidentIDs(ids...) +} + +// Where appends a list predicates to the ComponentUpdate builder. +func (_u *ComponentUpdateOne) Where(ps ...predicate.Component) *ComponentUpdateOne { + _u.mutation.Where(ps...) + return _u +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (_u *ComponentUpdateOne) Select(field string, fields ...string) *ComponentUpdateOne { + _u.fields = append([]string{field}, fields...) + return _u +} + +// Save executes the query and returns the updated Component entity. +func (_u *ComponentUpdateOne) Save(ctx context.Context) (*Component, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *ComponentUpdateOne) SaveX(ctx context.Context) *Component { + node, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (_u *ComponentUpdateOne) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *ComponentUpdateOne) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *ComponentUpdateOne) check() error { + if v, ok := _u.mutation.Name(); ok { + if err := component.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Component.name": %w`, err)} + } + } + return nil +} + +func (_u *ComponentUpdateOne) sqlSave(ctx context.Context) (_node *Component, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(component.Table, component.Columns, sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt)) + id, ok := _u.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Component.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := _u.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, component.FieldID) + for _, f := range fields { + if !component.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != component.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.Name(); ok { + _spec.SetField(component.FieldName, field.TypeString, value) + } + if value, ok := _u.mutation.CreatedAt(); ok { + _spec.SetField(component.FieldCreatedAt, field.TypeTime, value) + } + if _u.mutation.CreatedAtCleared() { + _spec.ClearField(component.FieldCreatedAt, field.TypeTime) + } + if value, ok := _u.mutation.ModifiedAt(); ok { + _spec.SetField(component.FieldModifiedAt, field.TypeTime, value) + } + if _u.mutation.ModifiedAtCleared() { + _spec.ClearField(component.FieldModifiedAt, field.TypeTime) + } + if value, ok := _u.mutation.DeletedAt(); ok { + _spec.SetField(component.FieldDeletedAt, field.TypeTime, value) + } + if _u.mutation.DeletedAtCleared() { + _spec.ClearField(component.FieldDeletedAt, field.TypeTime) + } + if _u.mutation.AttributesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: component.AttributesTable, + Columns: []string{component.AttributesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.RemovedAttributesIDs(); len(nodes) > 0 && !_u.mutation.AttributesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: component.AttributesTable, + Columns: []string{component.AttributesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.AttributesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: component.AttributesTable, + Columns: []string{component.AttributesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _u.mutation.IncidentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: component.IncidentsTable, + Columns: component.IncidentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.RemovedIncidentsIDs(); len(nodes) > 0 && !_u.mutation.IncidentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: component.IncidentsTable, + Columns: component.IncidentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.IncidentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: component.IncidentsTable, + Columns: component.IncidentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &Component{config: _u.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{component.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + _u.mutation.done = true + return _node, nil +} diff --git a/ent/componentattr.go b/ent/componentattr.go new file mode 100644 index 0000000..0bd41e7 --- /dev/null +++ b/ent/componentattr.go @@ -0,0 +1,154 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" +) + +// ComponentAttr is the model entity for the ComponentAttr schema. +type ComponentAttr struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // ComponentID holds the value of the "component_id" field. + ComponentID int `json:"component_id,omitempty"` + // Name holds the value of the "name" field. + Name string `json:"name,omitempty"` + // Value holds the value of the "value" field. + Value string `json:"value,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the ComponentAttrQuery when eager-loading is set. + Edges ComponentAttrEdges `json:"edges"` + selectValues sql.SelectValues +} + +// ComponentAttrEdges holds the relations/edges for other nodes in the graph. +type ComponentAttrEdges struct { + // Component holds the value of the component edge. + Component *Component `json:"component,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// ComponentOrErr returns the Component value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e ComponentAttrEdges) ComponentOrErr() (*Component, error) { + if e.Component != nil { + return e.Component, nil + } else if e.loadedTypes[0] { + return nil, &NotFoundError{label: component.Label} + } + return nil, &NotLoadedError{edge: "component"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*ComponentAttr) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case componentattr.FieldID, componentattr.FieldComponentID: + values[i] = new(sql.NullInt64) + case componentattr.FieldName, componentattr.FieldValue: + values[i] = new(sql.NullString) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the ComponentAttr fields. +func (_m *ComponentAttr) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case componentattr.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + _m.ID = int(value.Int64) + case componentattr.FieldComponentID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field component_id", values[i]) + } else if value.Valid { + _m.ComponentID = int(value.Int64) + } + case componentattr.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + _m.Name = value.String + } + case componentattr.FieldValue: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field value", values[i]) + } else if value.Valid { + _m.Value = value.String + } + default: + _m.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// GetValue returns the ent.Value that was dynamically selected and assigned to the ComponentAttr. +// This includes values selected through modifiers, order, etc. +func (_m *ComponentAttr) GetValue(name string) (ent.Value, error) { + return _m.selectValues.Get(name) +} + +// QueryComponent queries the "component" edge of the ComponentAttr entity. +func (_m *ComponentAttr) QueryComponent() *ComponentQuery { + return NewComponentAttrClient(_m.config).QueryComponent(_m) +} + +// Update returns a builder for updating this ComponentAttr. +// Note that you need to call ComponentAttr.Unwrap() before calling this method if this ComponentAttr +// was returned from a transaction, and the transaction was committed or rolled back. +func (_m *ComponentAttr) Update() *ComponentAttrUpdateOne { + return NewComponentAttrClient(_m.config).UpdateOne(_m) +} + +// Unwrap unwraps the ComponentAttr entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (_m *ComponentAttr) Unwrap() *ComponentAttr { + _tx, ok := _m.config.driver.(*txDriver) + if !ok { + panic("ent: ComponentAttr is not a transactional entity") + } + _m.config.driver = _tx.drv + return _m +} + +// String implements the fmt.Stringer. +func (_m *ComponentAttr) String() string { + var builder strings.Builder + builder.WriteString("ComponentAttr(") + builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID)) + builder.WriteString("component_id=") + builder.WriteString(fmt.Sprintf("%v", _m.ComponentID)) + builder.WriteString(", ") + builder.WriteString("name=") + builder.WriteString(_m.Name) + builder.WriteString(", ") + builder.WriteString("value=") + builder.WriteString(_m.Value) + builder.WriteByte(')') + return builder.String() +} + +// ComponentAttrs is a parsable slice of ComponentAttr. +type ComponentAttrs []*ComponentAttr diff --git a/ent/componentattr/componentattr.go b/ent/componentattr/componentattr.go new file mode 100644 index 0000000..6d3ba9a --- /dev/null +++ b/ent/componentattr/componentattr.go @@ -0,0 +1,94 @@ +// Code generated by ent, DO NOT EDIT. + +package componentattr + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the componentattr type in the database. + Label = "component_attr" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldComponentID holds the string denoting the component_id field in the database. + FieldComponentID = "component_id" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldValue holds the string denoting the value field in the database. + FieldValue = "value" + // EdgeComponent holds the string denoting the component edge name in mutations. + EdgeComponent = "component" + // Table holds the table name of the componentattr in the database. + Table = "component_attribute" + // ComponentTable is the table that holds the component relation/edge. + ComponentTable = "component_attribute" + // ComponentInverseTable is the table name for the Component entity. + // It exists in this package in order to avoid circular dependency with the "component" package. + ComponentInverseTable = "component" + // ComponentColumn is the table column denoting the component relation/edge. + ComponentColumn = "component_id" +) + +// Columns holds all SQL columns for componentattr fields. +var Columns = []string{ + FieldID, + FieldComponentID, + FieldName, + FieldValue, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error + // ValueValidator is a validator for the "value" field. It is called by the builders before save. + ValueValidator func(string) error +) + +// OrderOption defines the ordering options for the ComponentAttr queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByComponentID orders the results by the component_id field. +func ByComponentID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldComponentID, opts...).ToFunc() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} + +// ByValue orders the results by the value field. +func ByValue(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldValue, opts...).ToFunc() +} + +// ByComponentField orders the results by component field. +func ByComponentField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newComponentStep(), sql.OrderByField(field, opts...)) + } +} +func newComponentStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ComponentInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ComponentTable, ComponentColumn), + ) +} diff --git a/ent/componentattr/where.go b/ent/componentattr/where.go new file mode 100644 index 0000000..8fda70a --- /dev/null +++ b/ent/componentattr/where.go @@ -0,0 +1,267 @@ +// Code generated by ent, DO NOT EDIT. + +package componentattr + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldLTE(FieldID, id)) +} + +// ComponentID applies equality check predicate on the "component_id" field. It's identical to ComponentIDEQ. +func ComponentID(v int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEQ(FieldComponentID, v)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEQ(FieldName, v)) +} + +// Value applies equality check predicate on the "value" field. It's identical to ValueEQ. +func Value(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEQ(FieldValue, v)) +} + +// ComponentIDEQ applies the EQ predicate on the "component_id" field. +func ComponentIDEQ(v int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEQ(FieldComponentID, v)) +} + +// ComponentIDNEQ applies the NEQ predicate on the "component_id" field. +func ComponentIDNEQ(v int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNEQ(FieldComponentID, v)) +} + +// ComponentIDIn applies the In predicate on the "component_id" field. +func ComponentIDIn(vs ...int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldIn(FieldComponentID, vs...)) +} + +// ComponentIDNotIn applies the NotIn predicate on the "component_id" field. +func ComponentIDNotIn(vs ...int) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNotIn(FieldComponentID, vs...)) +} + +// ComponentIDIsNil applies the IsNil predicate on the "component_id" field. +func ComponentIDIsNil() predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldIsNull(FieldComponentID)) +} + +// ComponentIDNotNil applies the NotNil predicate on the "component_id" field. +func ComponentIDNotNil() predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNotNull(FieldComponentID)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldContainsFold(FieldName, v)) +} + +// ValueEQ applies the EQ predicate on the "value" field. +func ValueEQ(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEQ(FieldValue, v)) +} + +// ValueNEQ applies the NEQ predicate on the "value" field. +func ValueNEQ(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNEQ(FieldValue, v)) +} + +// ValueIn applies the In predicate on the "value" field. +func ValueIn(vs ...string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldIn(FieldValue, vs...)) +} + +// ValueNotIn applies the NotIn predicate on the "value" field. +func ValueNotIn(vs ...string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldNotIn(FieldValue, vs...)) +} + +// ValueGT applies the GT predicate on the "value" field. +func ValueGT(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldGT(FieldValue, v)) +} + +// ValueGTE applies the GTE predicate on the "value" field. +func ValueGTE(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldGTE(FieldValue, v)) +} + +// ValueLT applies the LT predicate on the "value" field. +func ValueLT(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldLT(FieldValue, v)) +} + +// ValueLTE applies the LTE predicate on the "value" field. +func ValueLTE(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldLTE(FieldValue, v)) +} + +// ValueContains applies the Contains predicate on the "value" field. +func ValueContains(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldContains(FieldValue, v)) +} + +// ValueHasPrefix applies the HasPrefix predicate on the "value" field. +func ValueHasPrefix(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldHasPrefix(FieldValue, v)) +} + +// ValueHasSuffix applies the HasSuffix predicate on the "value" field. +func ValueHasSuffix(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldHasSuffix(FieldValue, v)) +} + +// ValueEqualFold applies the EqualFold predicate on the "value" field. +func ValueEqualFold(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldEqualFold(FieldValue, v)) +} + +// ValueContainsFold applies the ContainsFold predicate on the "value" field. +func ValueContainsFold(v string) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.FieldContainsFold(FieldValue, v)) +} + +// HasComponent applies the HasEdge predicate on the "component" edge. +func HasComponent() predicate.ComponentAttr { + return predicate.ComponentAttr(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ComponentTable, ComponentColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasComponentWith applies the HasEdge predicate on the "component" edge with a given conditions (other predicates). +func HasComponentWith(preds ...predicate.Component) predicate.ComponentAttr { + return predicate.ComponentAttr(func(s *sql.Selector) { + step := newComponentStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.ComponentAttr) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.ComponentAttr) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.ComponentAttr) predicate.ComponentAttr { + return predicate.ComponentAttr(sql.NotPredicates(p)) +} diff --git a/ent/componentattr_create.go b/ent/componentattr_create.go new file mode 100644 index 0000000..4f2aed0 --- /dev/null +++ b/ent/componentattr_create.go @@ -0,0 +1,644 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" +) + +// ComponentAttrCreate is the builder for creating a ComponentAttr entity. +type ComponentAttrCreate struct { + config + mutation *ComponentAttrMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetComponentID sets the "component_id" field. +func (_c *ComponentAttrCreate) SetComponentID(v int) *ComponentAttrCreate { + _c.mutation.SetComponentID(v) + return _c +} + +// SetNillableComponentID sets the "component_id" field if the given value is not nil. +func (_c *ComponentAttrCreate) SetNillableComponentID(v *int) *ComponentAttrCreate { + if v != nil { + _c.SetComponentID(*v) + } + return _c +} + +// SetName sets the "name" field. +func (_c *ComponentAttrCreate) SetName(v string) *ComponentAttrCreate { + _c.mutation.SetName(v) + return _c +} + +// SetValue sets the "value" field. +func (_c *ComponentAttrCreate) SetValue(v string) *ComponentAttrCreate { + _c.mutation.SetValue(v) + return _c +} + +// SetID sets the "id" field. +func (_c *ComponentAttrCreate) SetID(v int) *ComponentAttrCreate { + _c.mutation.SetID(v) + return _c +} + +// SetComponent sets the "component" edge to the Component entity. +func (_c *ComponentAttrCreate) SetComponent(v *Component) *ComponentAttrCreate { + return _c.SetComponentID(v.ID) +} + +// Mutation returns the ComponentAttrMutation object of the builder. +func (_c *ComponentAttrCreate) Mutation() *ComponentAttrMutation { + return _c.mutation +} + +// Save creates the ComponentAttr in the database. +func (_c *ComponentAttrCreate) Save(ctx context.Context) (*ComponentAttr, error) { + return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (_c *ComponentAttrCreate) SaveX(ctx context.Context) *ComponentAttr { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *ComponentAttrCreate) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *ComponentAttrCreate) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_c *ComponentAttrCreate) check() error { + if _, ok := _c.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "ComponentAttr.name"`)} + } + if v, ok := _c.mutation.Name(); ok { + if err := componentattr.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ComponentAttr.name": %w`, err)} + } + } + if _, ok := _c.mutation.Value(); !ok { + return &ValidationError{Name: "value", err: errors.New(`ent: missing required field "ComponentAttr.value"`)} + } + if v, ok := _c.mutation.Value(); ok { + if err := componentattr.ValueValidator(v); err != nil { + return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "ComponentAttr.value": %w`, err)} + } + } + return nil +} + +func (_c *ComponentAttrCreate) sqlSave(ctx context.Context) (*ComponentAttr, error) { + if err := _c.check(); err != nil { + return nil, err + } + _node, _spec := _c.createSpec() + if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int(id) + } + _c.mutation.id = &_node.ID + _c.mutation.done = true + return _node, nil +} + +func (_c *ComponentAttrCreate) createSpec() (*ComponentAttr, *sqlgraph.CreateSpec) { + var ( + _node = &ComponentAttr{config: _c.config} + _spec = sqlgraph.NewCreateSpec(componentattr.Table, sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt)) + ) + _spec.OnConflict = _c.conflict + if id, ok := _c.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := _c.mutation.Name(); ok { + _spec.SetField(componentattr.FieldName, field.TypeString, value) + _node.Name = value + } + if value, ok := _c.mutation.Value(); ok { + _spec.SetField(componentattr.FieldValue, field.TypeString, value) + _node.Value = value + } + if nodes := _c.mutation.ComponentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: componentattr.ComponentTable, + Columns: []string{componentattr.ComponentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.ComponentID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.ComponentAttr.Create(). +// SetComponentID(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.ComponentAttrUpsert) { +// SetComponentID(v+v). +// }). +// Exec(ctx) +func (_c *ComponentAttrCreate) OnConflict(opts ...sql.ConflictOption) *ComponentAttrUpsertOne { + _c.conflict = opts + return &ComponentAttrUpsertOne{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.ComponentAttr.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *ComponentAttrCreate) OnConflictColumns(columns ...string) *ComponentAttrUpsertOne { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &ComponentAttrUpsertOne{ + create: _c, + } +} + +type ( + // ComponentAttrUpsertOne is the builder for "upsert"-ing + // one ComponentAttr node. + ComponentAttrUpsertOne struct { + create *ComponentAttrCreate + } + + // ComponentAttrUpsert is the "OnConflict" setter. + ComponentAttrUpsert struct { + *sql.UpdateSet + } +) + +// SetComponentID sets the "component_id" field. +func (u *ComponentAttrUpsert) SetComponentID(v int) *ComponentAttrUpsert { + u.Set(componentattr.FieldComponentID, v) + return u +} + +// UpdateComponentID sets the "component_id" field to the value that was provided on create. +func (u *ComponentAttrUpsert) UpdateComponentID() *ComponentAttrUpsert { + u.SetExcluded(componentattr.FieldComponentID) + return u +} + +// ClearComponentID clears the value of the "component_id" field. +func (u *ComponentAttrUpsert) ClearComponentID() *ComponentAttrUpsert { + u.SetNull(componentattr.FieldComponentID) + return u +} + +// SetName sets the "name" field. +func (u *ComponentAttrUpsert) SetName(v string) *ComponentAttrUpsert { + u.Set(componentattr.FieldName, v) + return u +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ComponentAttrUpsert) UpdateName() *ComponentAttrUpsert { + u.SetExcluded(componentattr.FieldName) + return u +} + +// SetValue sets the "value" field. +func (u *ComponentAttrUpsert) SetValue(v string) *ComponentAttrUpsert { + u.Set(componentattr.FieldValue, v) + return u +} + +// UpdateValue sets the "value" field to the value that was provided on create. +func (u *ComponentAttrUpsert) UpdateValue() *ComponentAttrUpsert { + u.SetExcluded(componentattr.FieldValue) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. +// Using this option is equivalent to using: +// +// client.ComponentAttr.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(componentattr.FieldID) +// }), +// ). +// Exec(ctx) +func (u *ComponentAttrUpsertOne) UpdateNewValues() *ComponentAttrUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.ID(); exists { + s.SetIgnore(componentattr.FieldID) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.ComponentAttr.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *ComponentAttrUpsertOne) Ignore() *ComponentAttrUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *ComponentAttrUpsertOne) DoNothing() *ComponentAttrUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the ComponentAttrCreate.OnConflict +// documentation for more info. +func (u *ComponentAttrUpsertOne) Update(set func(*ComponentAttrUpsert)) *ComponentAttrUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&ComponentAttrUpsert{UpdateSet: update}) + })) + return u +} + +// SetComponentID sets the "component_id" field. +func (u *ComponentAttrUpsertOne) SetComponentID(v int) *ComponentAttrUpsertOne { + return u.Update(func(s *ComponentAttrUpsert) { + s.SetComponentID(v) + }) +} + +// UpdateComponentID sets the "component_id" field to the value that was provided on create. +func (u *ComponentAttrUpsertOne) UpdateComponentID() *ComponentAttrUpsertOne { + return u.Update(func(s *ComponentAttrUpsert) { + s.UpdateComponentID() + }) +} + +// ClearComponentID clears the value of the "component_id" field. +func (u *ComponentAttrUpsertOne) ClearComponentID() *ComponentAttrUpsertOne { + return u.Update(func(s *ComponentAttrUpsert) { + s.ClearComponentID() + }) +} + +// SetName sets the "name" field. +func (u *ComponentAttrUpsertOne) SetName(v string) *ComponentAttrUpsertOne { + return u.Update(func(s *ComponentAttrUpsert) { + s.SetName(v) + }) +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ComponentAttrUpsertOne) UpdateName() *ComponentAttrUpsertOne { + return u.Update(func(s *ComponentAttrUpsert) { + s.UpdateName() + }) +} + +// SetValue sets the "value" field. +func (u *ComponentAttrUpsertOne) SetValue(v string) *ComponentAttrUpsertOne { + return u.Update(func(s *ComponentAttrUpsert) { + s.SetValue(v) + }) +} + +// UpdateValue sets the "value" field to the value that was provided on create. +func (u *ComponentAttrUpsertOne) UpdateValue() *ComponentAttrUpsertOne { + return u.Update(func(s *ComponentAttrUpsert) { + s.UpdateValue() + }) +} + +// Exec executes the query. +func (u *ComponentAttrUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for ComponentAttrCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *ComponentAttrUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *ComponentAttrUpsertOne) ID(ctx context.Context) (id int, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *ComponentAttrUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// ComponentAttrCreateBulk is the builder for creating many ComponentAttr entities in bulk. +type ComponentAttrCreateBulk struct { + config + err error + builders []*ComponentAttrCreate + conflict []sql.ConflictOption +} + +// Save creates the ComponentAttr entities in the database. +func (_c *ComponentAttrCreateBulk) Save(ctx context.Context) ([]*ComponentAttr, error) { + if _c.err != nil { + return nil, _c.err + } + specs := make([]*sqlgraph.CreateSpec, len(_c.builders)) + nodes := make([]*ComponentAttr, len(_c.builders)) + mutators := make([]Mutator, len(_c.builders)) + for i := range _c.builders { + func(i int, root context.Context) { + builder := _c.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ComponentAttrMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = _c.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (_c *ComponentAttrCreateBulk) SaveX(ctx context.Context) []*ComponentAttr { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *ComponentAttrCreateBulk) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *ComponentAttrCreateBulk) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.ComponentAttr.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.ComponentAttrUpsert) { +// SetComponentID(v+v). +// }). +// Exec(ctx) +func (_c *ComponentAttrCreateBulk) OnConflict(opts ...sql.ConflictOption) *ComponentAttrUpsertBulk { + _c.conflict = opts + return &ComponentAttrUpsertBulk{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.ComponentAttr.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *ComponentAttrCreateBulk) OnConflictColumns(columns ...string) *ComponentAttrUpsertBulk { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &ComponentAttrUpsertBulk{ + create: _c, + } +} + +// ComponentAttrUpsertBulk is the builder for "upsert"-ing +// a bulk of ComponentAttr nodes. +type ComponentAttrUpsertBulk struct { + create *ComponentAttrCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.ComponentAttr.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(componentattr.FieldID) +// }), +// ). +// Exec(ctx) +func (u *ComponentAttrUpsertBulk) UpdateNewValues() *ComponentAttrUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.ID(); exists { + s.SetIgnore(componentattr.FieldID) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.ComponentAttr.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *ComponentAttrUpsertBulk) Ignore() *ComponentAttrUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *ComponentAttrUpsertBulk) DoNothing() *ComponentAttrUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the ComponentAttrCreateBulk.OnConflict +// documentation for more info. +func (u *ComponentAttrUpsertBulk) Update(set func(*ComponentAttrUpsert)) *ComponentAttrUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&ComponentAttrUpsert{UpdateSet: update}) + })) + return u +} + +// SetComponentID sets the "component_id" field. +func (u *ComponentAttrUpsertBulk) SetComponentID(v int) *ComponentAttrUpsertBulk { + return u.Update(func(s *ComponentAttrUpsert) { + s.SetComponentID(v) + }) +} + +// UpdateComponentID sets the "component_id" field to the value that was provided on create. +func (u *ComponentAttrUpsertBulk) UpdateComponentID() *ComponentAttrUpsertBulk { + return u.Update(func(s *ComponentAttrUpsert) { + s.UpdateComponentID() + }) +} + +// ClearComponentID clears the value of the "component_id" field. +func (u *ComponentAttrUpsertBulk) ClearComponentID() *ComponentAttrUpsertBulk { + return u.Update(func(s *ComponentAttrUpsert) { + s.ClearComponentID() + }) +} + +// SetName sets the "name" field. +func (u *ComponentAttrUpsertBulk) SetName(v string) *ComponentAttrUpsertBulk { + return u.Update(func(s *ComponentAttrUpsert) { + s.SetName(v) + }) +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ComponentAttrUpsertBulk) UpdateName() *ComponentAttrUpsertBulk { + return u.Update(func(s *ComponentAttrUpsert) { + s.UpdateName() + }) +} + +// SetValue sets the "value" field. +func (u *ComponentAttrUpsertBulk) SetValue(v string) *ComponentAttrUpsertBulk { + return u.Update(func(s *ComponentAttrUpsert) { + s.SetValue(v) + }) +} + +// UpdateValue sets the "value" field to the value that was provided on create. +func (u *ComponentAttrUpsertBulk) UpdateValue() *ComponentAttrUpsertBulk { + return u.Update(func(s *ComponentAttrUpsert) { + s.UpdateValue() + }) +} + +// Exec executes the query. +func (u *ComponentAttrUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ComponentAttrCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for ComponentAttrCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *ComponentAttrUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/componentattr_delete.go b/ent/componentattr_delete.go new file mode 100644 index 0000000..ea6e688 --- /dev/null +++ b/ent/componentattr_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ComponentAttrDelete is the builder for deleting a ComponentAttr entity. +type ComponentAttrDelete struct { + config + hooks []Hook + mutation *ComponentAttrMutation +} + +// Where appends a list predicates to the ComponentAttrDelete builder. +func (_d *ComponentAttrDelete) Where(ps ...predicate.ComponentAttr) *ComponentAttrDelete { + _d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (_d *ComponentAttrDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *ComponentAttrDelete) ExecX(ctx context.Context) int { + n, err := _d.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (_d *ComponentAttrDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(componentattr.Table, sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt)) + if ps := _d.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + _d.mutation.done = true + return affected, err +} + +// ComponentAttrDeleteOne is the builder for deleting a single ComponentAttr entity. +type ComponentAttrDeleteOne struct { + _d *ComponentAttrDelete +} + +// Where appends a list predicates to the ComponentAttrDelete builder. +func (_d *ComponentAttrDeleteOne) Where(ps ...predicate.ComponentAttr) *ComponentAttrDeleteOne { + _d._d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query. +func (_d *ComponentAttrDeleteOne) Exec(ctx context.Context) error { + n, err := _d._d.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{componentattr.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *ComponentAttrDeleteOne) ExecX(ctx context.Context) { + if err := _d.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/componentattr_query.go b/ent/componentattr_query.go new file mode 100644 index 0000000..1800989 --- /dev/null +++ b/ent/componentattr_query.go @@ -0,0 +1,606 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ComponentAttrQuery is the builder for querying ComponentAttr entities. +type ComponentAttrQuery struct { + config + ctx *QueryContext + order []componentattr.OrderOption + inters []Interceptor + predicates []predicate.ComponentAttr + withComponent *ComponentQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the ComponentAttrQuery builder. +func (_q *ComponentAttrQuery) Where(ps ...predicate.ComponentAttr) *ComponentAttrQuery { + _q.predicates = append(_q.predicates, ps...) + return _q +} + +// Limit the number of records to be returned by this query. +func (_q *ComponentAttrQuery) Limit(limit int) *ComponentAttrQuery { + _q.ctx.Limit = &limit + return _q +} + +// Offset to start from. +func (_q *ComponentAttrQuery) Offset(offset int) *ComponentAttrQuery { + _q.ctx.Offset = &offset + return _q +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (_q *ComponentAttrQuery) Unique(unique bool) *ComponentAttrQuery { + _q.ctx.Unique = &unique + return _q +} + +// Order specifies how the records should be ordered. +func (_q *ComponentAttrQuery) Order(o ...componentattr.OrderOption) *ComponentAttrQuery { + _q.order = append(_q.order, o...) + return _q +} + +// QueryComponent chains the current query on the "component" edge. +func (_q *ComponentAttrQuery) QueryComponent() *ComponentQuery { + query := (&ComponentClient{config: _q.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + selector := _q.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(componentattr.Table, componentattr.FieldID, selector), + sqlgraph.To(component.Table, component.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, componentattr.ComponentTable, componentattr.ComponentColumn), + ) + fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first ComponentAttr entity from the query. +// Returns a *NotFoundError when no ComponentAttr was found. +func (_q *ComponentAttrQuery) First(ctx context.Context) (*ComponentAttr, error) { + nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{componentattr.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (_q *ComponentAttrQuery) FirstX(ctx context.Context) *ComponentAttr { + node, err := _q.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first ComponentAttr ID from the query. +// Returns a *NotFoundError when no ComponentAttr ID was found. +func (_q *ComponentAttrQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{componentattr.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (_q *ComponentAttrQuery) FirstIDX(ctx context.Context) int { + id, err := _q.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single ComponentAttr entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one ComponentAttr entity is found. +// Returns a *NotFoundError when no ComponentAttr entities are found. +func (_q *ComponentAttrQuery) Only(ctx context.Context) (*ComponentAttr, error) { + nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{componentattr.Label} + default: + return nil, &NotSingularError{componentattr.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (_q *ComponentAttrQuery) OnlyX(ctx context.Context) *ComponentAttr { + node, err := _q.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only ComponentAttr ID in the query. +// Returns a *NotSingularError when more than one ComponentAttr ID is found. +// Returns a *NotFoundError when no entities are found. +func (_q *ComponentAttrQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{componentattr.Label} + default: + err = &NotSingularError{componentattr.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (_q *ComponentAttrQuery) OnlyIDX(ctx context.Context) int { + id, err := _q.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of ComponentAttrs. +func (_q *ComponentAttrQuery) All(ctx context.Context) ([]*ComponentAttr, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll) + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*ComponentAttr, *ComponentAttrQuery]() + return withInterceptors[[]*ComponentAttr](ctx, _q, qr, _q.inters) +} + +// AllX is like All, but panics if an error occurs. +func (_q *ComponentAttrQuery) AllX(ctx context.Context) []*ComponentAttr { + nodes, err := _q.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of ComponentAttr IDs. +func (_q *ComponentAttrQuery) IDs(ctx context.Context) (ids []int, err error) { + if _q.ctx.Unique == nil && _q.path != nil { + _q.Unique(true) + } + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs) + if err = _q.Select(componentattr.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (_q *ComponentAttrQuery) IDsX(ctx context.Context) []int { + ids, err := _q.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (_q *ComponentAttrQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount) + if err := _q.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, _q, querierCount[*ComponentAttrQuery](), _q.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (_q *ComponentAttrQuery) CountX(ctx context.Context) int { + count, err := _q.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (_q *ComponentAttrQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist) + switch _, err := _q.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (_q *ComponentAttrQuery) ExistX(ctx context.Context) bool { + exist, err := _q.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the ComponentAttrQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (_q *ComponentAttrQuery) Clone() *ComponentAttrQuery { + if _q == nil { + return nil + } + return &ComponentAttrQuery{ + config: _q.config, + ctx: _q.ctx.Clone(), + order: append([]componentattr.OrderOption{}, _q.order...), + inters: append([]Interceptor{}, _q.inters...), + predicates: append([]predicate.ComponentAttr{}, _q.predicates...), + withComponent: _q.withComponent.Clone(), + // clone intermediate query. + sql: _q.sql.Clone(), + path: _q.path, + } +} + +// WithComponent tells the query-builder to eager-load the nodes that are connected to +// the "component" edge. The optional arguments are used to configure the query builder of the edge. +func (_q *ComponentAttrQuery) WithComponent(opts ...func(*ComponentQuery)) *ComponentAttrQuery { + query := (&ComponentClient{config: _q.config}).Query() + for _, opt := range opts { + opt(query) + } + _q.withComponent = query + return _q +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// ComponentID int `json:"component_id,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.ComponentAttr.Query(). +// GroupBy(componentattr.FieldComponentID). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (_q *ComponentAttrQuery) GroupBy(field string, fields ...string) *ComponentAttrGroupBy { + _q.ctx.Fields = append([]string{field}, fields...) + grbuild := &ComponentAttrGroupBy{build: _q} + grbuild.flds = &_q.ctx.Fields + grbuild.label = componentattr.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// ComponentID int `json:"component_id,omitempty"` +// } +// +// client.ComponentAttr.Query(). +// Select(componentattr.FieldComponentID). +// Scan(ctx, &v) +func (_q *ComponentAttrQuery) Select(fields ...string) *ComponentAttrSelect { + _q.ctx.Fields = append(_q.ctx.Fields, fields...) + sbuild := &ComponentAttrSelect{ComponentAttrQuery: _q} + sbuild.label = componentattr.Label + sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a ComponentAttrSelect configured with the given aggregations. +func (_q *ComponentAttrQuery) Aggregate(fns ...AggregateFunc) *ComponentAttrSelect { + return _q.Select().Aggregate(fns...) +} + +func (_q *ComponentAttrQuery) prepareQuery(ctx context.Context) error { + for _, inter := range _q.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, _q); err != nil { + return err + } + } + } + for _, f := range _q.ctx.Fields { + if !componentattr.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if _q.path != nil { + prev, err := _q.path(ctx) + if err != nil { + return err + } + _q.sql = prev + } + return nil +} + +func (_q *ComponentAttrQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*ComponentAttr, error) { + var ( + nodes = []*ComponentAttr{} + _spec = _q.querySpec() + loadedTypes = [1]bool{ + _q.withComponent != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*ComponentAttr).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &ComponentAttr{config: _q.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := _q.withComponent; query != nil { + if err := _q.loadComponent(ctx, query, nodes, nil, + func(n *ComponentAttr, e *Component) { n.Edges.Component = e }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (_q *ComponentAttrQuery) loadComponent(ctx context.Context, query *ComponentQuery, nodes []*ComponentAttr, init func(*ComponentAttr), assign func(*ComponentAttr, *Component)) error { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*ComponentAttr) + for i := range nodes { + fk := nodes[i].ComponentID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(component.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "component_id" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + +func (_q *ComponentAttrQuery) sqlCount(ctx context.Context) (int, error) { + _spec := _q.querySpec() + _spec.Node.Columns = _q.ctx.Fields + if len(_q.ctx.Fields) > 0 { + _spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique + } + return sqlgraph.CountNodes(ctx, _q.driver, _spec) +} + +func (_q *ComponentAttrQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(componentattr.Table, componentattr.Columns, sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt)) + _spec.From = _q.sql + if unique := _q.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if _q.path != nil { + _spec.Unique = true + } + if fields := _q.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, componentattr.FieldID) + for i := range fields { + if fields[i] != componentattr.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + if _q.withComponent != nil { + _spec.Node.AddColumnOnce(componentattr.FieldComponentID) + } + } + if ps := _q.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := _q.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := _q.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := _q.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (_q *ComponentAttrQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(_q.driver.Dialect()) + t1 := builder.Table(componentattr.Table) + columns := _q.ctx.Fields + if len(columns) == 0 { + columns = componentattr.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if _q.sql != nil { + selector = _q.sql + selector.Select(selector.Columns(columns...)...) + } + if _q.ctx.Unique != nil && *_q.ctx.Unique { + selector.Distinct() + } + for _, p := range _q.predicates { + p(selector) + } + for _, p := range _q.order { + p(selector) + } + if offset := _q.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := _q.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ComponentAttrGroupBy is the group-by builder for ComponentAttr entities. +type ComponentAttrGroupBy struct { + selector + build *ComponentAttrQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (_g *ComponentAttrGroupBy) Aggregate(fns ...AggregateFunc) *ComponentAttrGroupBy { + _g.fns = append(_g.fns, fns...) + return _g +} + +// Scan applies the selector query and scans the result into the given value. +func (_g *ComponentAttrGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy) + if err := _g.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*ComponentAttrQuery, *ComponentAttrGroupBy](ctx, _g.build, _g, _g.build.inters, v) +} + +func (_g *ComponentAttrGroupBy) sqlScan(ctx context.Context, root *ComponentAttrQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(_g.fns)) + for _, fn := range _g.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*_g.flds)+len(_g.fns)) + for _, f := range *_g.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*_g.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _g.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// ComponentAttrSelect is the builder for selecting fields of ComponentAttr entities. +type ComponentAttrSelect struct { + *ComponentAttrQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (_s *ComponentAttrSelect) Aggregate(fns ...AggregateFunc) *ComponentAttrSelect { + _s.fns = append(_s.fns, fns...) + return _s +} + +// Scan applies the selector query and scans the result into the given value. +func (_s *ComponentAttrSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect) + if err := _s.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*ComponentAttrQuery, *ComponentAttrSelect](ctx, _s.ComponentAttrQuery, _s, _s.inters, v) +} + +func (_s *ComponentAttrSelect) sqlScan(ctx context.Context, root *ComponentAttrQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(_s.fns)) + for _, fn := range _s.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*_s.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _s.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/componentattr_update.go b/ent/componentattr_update.go new file mode 100644 index 0000000..be3139d --- /dev/null +++ b/ent/componentattr_update.go @@ -0,0 +1,400 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ComponentAttrUpdate is the builder for updating ComponentAttr entities. +type ComponentAttrUpdate struct { + config + hooks []Hook + mutation *ComponentAttrMutation +} + +// Where appends a list predicates to the ComponentAttrUpdate builder. +func (_u *ComponentAttrUpdate) Where(ps ...predicate.ComponentAttr) *ComponentAttrUpdate { + _u.mutation.Where(ps...) + return _u +} + +// SetComponentID sets the "component_id" field. +func (_u *ComponentAttrUpdate) SetComponentID(v int) *ComponentAttrUpdate { + _u.mutation.SetComponentID(v) + return _u +} + +// SetNillableComponentID sets the "component_id" field if the given value is not nil. +func (_u *ComponentAttrUpdate) SetNillableComponentID(v *int) *ComponentAttrUpdate { + if v != nil { + _u.SetComponentID(*v) + } + return _u +} + +// ClearComponentID clears the value of the "component_id" field. +func (_u *ComponentAttrUpdate) ClearComponentID() *ComponentAttrUpdate { + _u.mutation.ClearComponentID() + return _u +} + +// SetName sets the "name" field. +func (_u *ComponentAttrUpdate) SetName(v string) *ComponentAttrUpdate { + _u.mutation.SetName(v) + return _u +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (_u *ComponentAttrUpdate) SetNillableName(v *string) *ComponentAttrUpdate { + if v != nil { + _u.SetName(*v) + } + return _u +} + +// SetValue sets the "value" field. +func (_u *ComponentAttrUpdate) SetValue(v string) *ComponentAttrUpdate { + _u.mutation.SetValue(v) + return _u +} + +// SetNillableValue sets the "value" field if the given value is not nil. +func (_u *ComponentAttrUpdate) SetNillableValue(v *string) *ComponentAttrUpdate { + if v != nil { + _u.SetValue(*v) + } + return _u +} + +// SetComponent sets the "component" edge to the Component entity. +func (_u *ComponentAttrUpdate) SetComponent(v *Component) *ComponentAttrUpdate { + return _u.SetComponentID(v.ID) +} + +// Mutation returns the ComponentAttrMutation object of the builder. +func (_u *ComponentAttrUpdate) Mutation() *ComponentAttrMutation { + return _u.mutation +} + +// ClearComponent clears the "component" edge to the Component entity. +func (_u *ComponentAttrUpdate) ClearComponent() *ComponentAttrUpdate { + _u.mutation.ClearComponent() + return _u +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (_u *ComponentAttrUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *ComponentAttrUpdate) SaveX(ctx context.Context) int { + affected, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (_u *ComponentAttrUpdate) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *ComponentAttrUpdate) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *ComponentAttrUpdate) check() error { + if v, ok := _u.mutation.Name(); ok { + if err := componentattr.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ComponentAttr.name": %w`, err)} + } + } + if v, ok := _u.mutation.Value(); ok { + if err := componentattr.ValueValidator(v); err != nil { + return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "ComponentAttr.value": %w`, err)} + } + } + return nil +} + +func (_u *ComponentAttrUpdate) sqlSave(ctx context.Context) (_node int, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(componentattr.Table, componentattr.Columns, sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt)) + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.Name(); ok { + _spec.SetField(componentattr.FieldName, field.TypeString, value) + } + if value, ok := _u.mutation.Value(); ok { + _spec.SetField(componentattr.FieldValue, field.TypeString, value) + } + if _u.mutation.ComponentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: componentattr.ComponentTable, + Columns: []string{componentattr.ComponentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.ComponentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: componentattr.ComponentTable, + Columns: []string{componentattr.ComponentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{componentattr.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + _u.mutation.done = true + return _node, nil +} + +// ComponentAttrUpdateOne is the builder for updating a single ComponentAttr entity. +type ComponentAttrUpdateOne struct { + config + fields []string + hooks []Hook + mutation *ComponentAttrMutation +} + +// SetComponentID sets the "component_id" field. +func (_u *ComponentAttrUpdateOne) SetComponentID(v int) *ComponentAttrUpdateOne { + _u.mutation.SetComponentID(v) + return _u +} + +// SetNillableComponentID sets the "component_id" field if the given value is not nil. +func (_u *ComponentAttrUpdateOne) SetNillableComponentID(v *int) *ComponentAttrUpdateOne { + if v != nil { + _u.SetComponentID(*v) + } + return _u +} + +// ClearComponentID clears the value of the "component_id" field. +func (_u *ComponentAttrUpdateOne) ClearComponentID() *ComponentAttrUpdateOne { + _u.mutation.ClearComponentID() + return _u +} + +// SetName sets the "name" field. +func (_u *ComponentAttrUpdateOne) SetName(v string) *ComponentAttrUpdateOne { + _u.mutation.SetName(v) + return _u +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (_u *ComponentAttrUpdateOne) SetNillableName(v *string) *ComponentAttrUpdateOne { + if v != nil { + _u.SetName(*v) + } + return _u +} + +// SetValue sets the "value" field. +func (_u *ComponentAttrUpdateOne) SetValue(v string) *ComponentAttrUpdateOne { + _u.mutation.SetValue(v) + return _u +} + +// SetNillableValue sets the "value" field if the given value is not nil. +func (_u *ComponentAttrUpdateOne) SetNillableValue(v *string) *ComponentAttrUpdateOne { + if v != nil { + _u.SetValue(*v) + } + return _u +} + +// SetComponent sets the "component" edge to the Component entity. +func (_u *ComponentAttrUpdateOne) SetComponent(v *Component) *ComponentAttrUpdateOne { + return _u.SetComponentID(v.ID) +} + +// Mutation returns the ComponentAttrMutation object of the builder. +func (_u *ComponentAttrUpdateOne) Mutation() *ComponentAttrMutation { + return _u.mutation +} + +// ClearComponent clears the "component" edge to the Component entity. +func (_u *ComponentAttrUpdateOne) ClearComponent() *ComponentAttrUpdateOne { + _u.mutation.ClearComponent() + return _u +} + +// Where appends a list predicates to the ComponentAttrUpdate builder. +func (_u *ComponentAttrUpdateOne) Where(ps ...predicate.ComponentAttr) *ComponentAttrUpdateOne { + _u.mutation.Where(ps...) + return _u +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (_u *ComponentAttrUpdateOne) Select(field string, fields ...string) *ComponentAttrUpdateOne { + _u.fields = append([]string{field}, fields...) + return _u +} + +// Save executes the query and returns the updated ComponentAttr entity. +func (_u *ComponentAttrUpdateOne) Save(ctx context.Context) (*ComponentAttr, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *ComponentAttrUpdateOne) SaveX(ctx context.Context) *ComponentAttr { + node, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (_u *ComponentAttrUpdateOne) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *ComponentAttrUpdateOne) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *ComponentAttrUpdateOne) check() error { + if v, ok := _u.mutation.Name(); ok { + if err := componentattr.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ComponentAttr.name": %w`, err)} + } + } + if v, ok := _u.mutation.Value(); ok { + if err := componentattr.ValueValidator(v); err != nil { + return &ValidationError{Name: "value", err: fmt.Errorf(`ent: validator failed for field "ComponentAttr.value": %w`, err)} + } + } + return nil +} + +func (_u *ComponentAttrUpdateOne) sqlSave(ctx context.Context) (_node *ComponentAttr, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(componentattr.Table, componentattr.Columns, sqlgraph.NewFieldSpec(componentattr.FieldID, field.TypeInt)) + id, ok := _u.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ComponentAttr.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := _u.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, componentattr.FieldID) + for _, f := range fields { + if !componentattr.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != componentattr.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.Name(); ok { + _spec.SetField(componentattr.FieldName, field.TypeString, value) + } + if value, ok := _u.mutation.Value(); ok { + _spec.SetField(componentattr.FieldValue, field.TypeString, value) + } + if _u.mutation.ComponentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: componentattr.ComponentTable, + Columns: []string{componentattr.ComponentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.ComponentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: componentattr.ComponentTable, + Columns: []string{componentattr.ComponentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &ComponentAttr{config: _u.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{componentattr.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + _u.mutation.done = true + return _node, nil +} diff --git a/ent/ent.go b/ent/ent.go new file mode 100644 index 0000000..c908945 --- /dev/null +++ b/ent/ent.go @@ -0,0 +1,616 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "reflect" + "sync" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" +) + +// ent aliases to avoid import conflicts in user's code. +type ( + Op = ent.Op + Hook = ent.Hook + Value = ent.Value + Query = ent.Query + QueryContext = ent.QueryContext + Querier = ent.Querier + QuerierFunc = ent.QuerierFunc + Interceptor = ent.Interceptor + InterceptFunc = ent.InterceptFunc + Traverser = ent.Traverser + TraverseFunc = ent.TraverseFunc + Policy = ent.Policy + Mutator = ent.Mutator + Mutation = ent.Mutation + MutateFunc = ent.MutateFunc +) + +type clientCtxKey struct{} + +// FromContext returns a Client stored inside a context, or nil if there isn't one. +func FromContext(ctx context.Context) *Client { + c, _ := ctx.Value(clientCtxKey{}).(*Client) + return c +} + +// NewContext returns a new context with the given Client attached. +func NewContext(parent context.Context, c *Client) context.Context { + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns a Tx stored inside a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Tx attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) +} + +// OrderFunc applies an ordering on the sql selector. +// Deprecated: Use Asc/Desc functions or the package builders instead. +type OrderFunc func(*sql.Selector) + +var ( + initCheck sync.Once + columnCheck sql.ColumnCheck +) + +// checkColumn checks if the column exists in the given table. +func checkColumn(t, c string) error { + initCheck.Do(func() { + columnCheck = sql.NewColumnCheck(map[string]func(string) bool{ + component.Table: component.ValidColumn, + componentattr.Table: componentattr.ValidColumn, + incident.Table: incident.ValidColumn, + incidentstatus.Table: incidentstatus.ValidColumn, + notificationoutbox.Table: notificationoutbox.ValidColumn, + }) + }) + return columnCheck(t, c) +} + +// Asc applies the given fields in ASC order. +func Asc(fields ...string) func(*sql.Selector) { + return func(s *sql.Selector) { + for _, f := range fields { + if err := checkColumn(s.TableName(), f); err != nil { + s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)}) + } + s.OrderBy(sql.Asc(s.C(f))) + } + } +} + +// Desc applies the given fields in DESC order. +func Desc(fields ...string) func(*sql.Selector) { + return func(s *sql.Selector) { + for _, f := range fields { + if err := checkColumn(s.TableName(), f); err != nil { + s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)}) + } + s.OrderBy(sql.Desc(s.C(f))) + } + } +} + +// AggregateFunc applies an aggregation step on the group-by traversal/selector. +type AggregateFunc func(*sql.Selector) string + +// As is a pseudo aggregation function for renaming another other functions with custom names. For example: +// +// GroupBy(field1, field2). +// Aggregate(ent.As(ent.Sum(field1), "sum_field1"), (ent.As(ent.Sum(field2), "sum_field2")). +// Scan(ctx, &v) +func As(fn AggregateFunc, end string) AggregateFunc { + return func(s *sql.Selector) string { + return sql.As(fn(s), end) + } +} + +// Count applies the "count" aggregation function on each group. +func Count() AggregateFunc { + return func(s *sql.Selector) string { + return sql.Count("*") + } +} + +// Max applies the "max" aggregation function on the given field of each group. +func Max(field string) AggregateFunc { + return func(s *sql.Selector) string { + if err := checkColumn(s.TableName(), field); err != nil { + s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) + return "" + } + return sql.Max(s.C(field)) + } +} + +// Mean applies the "mean" aggregation function on the given field of each group. +func Mean(field string) AggregateFunc { + return func(s *sql.Selector) string { + if err := checkColumn(s.TableName(), field); err != nil { + s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) + return "" + } + return sql.Avg(s.C(field)) + } +} + +// Min applies the "min" aggregation function on the given field of each group. +func Min(field string) AggregateFunc { + return func(s *sql.Selector) string { + if err := checkColumn(s.TableName(), field); err != nil { + s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) + return "" + } + return sql.Min(s.C(field)) + } +} + +// Sum applies the "sum" aggregation function on the given field of each group. +func Sum(field string) AggregateFunc { + return func(s *sql.Selector) string { + if err := checkColumn(s.TableName(), field); err != nil { + s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) + return "" + } + return sql.Sum(s.C(field)) + } +} + +// ValidationError returns when validating a field or edge fails. +type ValidationError struct { + Name string // Field or edge name. + err error +} + +// Error implements the error interface. +func (e *ValidationError) Error() string { + return e.err.Error() +} + +// Unwrap implements the errors.Wrapper interface. +func (e *ValidationError) Unwrap() error { + return e.err +} + +// IsValidationError returns a boolean indicating whether the error is a validation error. +func IsValidationError(err error) bool { + if err == nil { + return false + } + var e *ValidationError + return errors.As(err, &e) +} + +// NotFoundError returns when trying to fetch a specific entity and it was not found in the database. +type NotFoundError struct { + label string +} + +// Error implements the error interface. +func (e *NotFoundError) Error() string { + return "ent: " + e.label + " not found" +} + +// IsNotFound returns a boolean indicating whether the error is a not found error. +func IsNotFound(err error) bool { + if err == nil { + return false + } + var e *NotFoundError + return errors.As(err, &e) +} + +// MaskNotFound masks not found error. +func MaskNotFound(err error) error { + if IsNotFound(err) { + return nil + } + return err +} + +// NotSingularError returns when trying to fetch a singular entity and more then one was found in the database. +type NotSingularError struct { + label string +} + +// Error implements the error interface. +func (e *NotSingularError) Error() string { + return "ent: " + e.label + " not singular" +} + +// IsNotSingular returns a boolean indicating whether the error is a not singular error. +func IsNotSingular(err error) bool { + if err == nil { + return false + } + var e *NotSingularError + return errors.As(err, &e) +} + +// NotLoadedError returns when trying to get a node that was not loaded by the query. +type NotLoadedError struct { + edge string +} + +// Error implements the error interface. +func (e *NotLoadedError) Error() string { + return "ent: " + e.edge + " edge was not loaded" +} + +// IsNotLoaded returns a boolean indicating whether the error is a not loaded error. +func IsNotLoaded(err error) bool { + if err == nil { + return false + } + var e *NotLoadedError + return errors.As(err, &e) +} + +// ConstraintError returns when trying to create/update one or more entities and +// one or more of their constraints failed. For example, violation of edge or +// field uniqueness. +type ConstraintError struct { + msg string + wrap error +} + +// Error implements the error interface. +func (e ConstraintError) Error() string { + return "ent: constraint failed: " + e.msg +} + +// Unwrap implements the errors.Wrapper interface. +func (e *ConstraintError) Unwrap() error { + return e.wrap +} + +// IsConstraintError returns a boolean indicating whether the error is a constraint failure. +func IsConstraintError(err error) bool { + if err == nil { + return false + } + var e *ConstraintError + return errors.As(err, &e) +} + +// selector embedded by the different Select/GroupBy builders. +type selector struct { + label string + flds *[]string + fns []AggregateFunc + scan func(context.Context, any) error +} + +// ScanX is like Scan, but panics if an error occurs. +func (s *selector) ScanX(ctx context.Context, v any) { + if err := s.scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from a selector. It is only allowed when selecting one field. +func (s *selector) Strings(ctx context.Context) ([]string, error) { + if len(*s.flds) > 1 { + return nil, errors.New("ent: Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := s.scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (s *selector) StringsX(ctx context.Context) []string { + v, err := s.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a selector. It is only allowed when selecting one field. +func (s *selector) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = s.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{s.label} + default: + err = fmt.Errorf("ent: Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (s *selector) StringX(ctx context.Context) string { + v, err := s.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from a selector. It is only allowed when selecting one field. +func (s *selector) Ints(ctx context.Context) ([]int, error) { + if len(*s.flds) > 1 { + return nil, errors.New("ent: Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := s.scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (s *selector) IntsX(ctx context.Context) []int { + v, err := s.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a selector. It is only allowed when selecting one field. +func (s *selector) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = s.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{s.label} + default: + err = fmt.Errorf("ent: Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (s *selector) IntX(ctx context.Context) int { + v, err := s.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from a selector. It is only allowed when selecting one field. +func (s *selector) Float64s(ctx context.Context) ([]float64, error) { + if len(*s.flds) > 1 { + return nil, errors.New("ent: Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := s.scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (s *selector) Float64sX(ctx context.Context) []float64 { + v, err := s.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a selector. It is only allowed when selecting one field. +func (s *selector) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = s.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{s.label} + default: + err = fmt.Errorf("ent: Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (s *selector) Float64X(ctx context.Context) float64 { + v, err := s.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from a selector. It is only allowed when selecting one field. +func (s *selector) Bools(ctx context.Context) ([]bool, error) { + if len(*s.flds) > 1 { + return nil, errors.New("ent: Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := s.scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (s *selector) BoolsX(ctx context.Context) []bool { + v, err := s.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a selector. It is only allowed when selecting one field. +func (s *selector) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = s.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{s.label} + default: + err = fmt.Errorf("ent: Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (s *selector) BoolX(ctx context.Context) bool { + v, err := s.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +// withHooks invokes the builder operation with the given hooks, if any. +func withHooks[V Value, M any, PM interface { + *M + Mutation +}](ctx context.Context, exec func(context.Context) (V, error), mutation PM, hooks []Hook) (value V, err error) { + if len(hooks) == 0 { + return exec(ctx) + } + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutationT, ok := any(m).(PM) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + // Set the mutation to the builder. + *mutation = *mutationT + return exec(ctx) + }) + for i := len(hooks) - 1; i >= 0; i-- { + if hooks[i] == nil { + return value, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = hooks[i](mut) + } + v, err := mut.Mutate(ctx, mutation) + if err != nil { + return value, err + } + nv, ok := v.(V) + if !ok { + return value, fmt.Errorf("unexpected node type %T returned from %T", v, mutation) + } + return nv, nil +} + +// setContextOp returns a new context with the given QueryContext attached (including its op) in case it does not exist. +func setContextOp(ctx context.Context, qc *QueryContext, op string) context.Context { + if ent.QueryFromContext(ctx) == nil { + qc.Op = op + ctx = ent.NewQueryContext(ctx, qc) + } + return ctx +} + +func querierAll[V Value, Q interface { + sqlAll(context.Context, ...queryHook) (V, error) +}]() Querier { + return QuerierFunc(func(ctx context.Context, q Query) (Value, error) { + query, ok := q.(Q) + if !ok { + return nil, fmt.Errorf("unexpected query type %T", q) + } + return query.sqlAll(ctx) + }) +} + +func querierCount[Q interface { + sqlCount(context.Context) (int, error) +}]() Querier { + return QuerierFunc(func(ctx context.Context, q Query) (Value, error) { + query, ok := q.(Q) + if !ok { + return nil, fmt.Errorf("unexpected query type %T", q) + } + return query.sqlCount(ctx) + }) +} + +func withInterceptors[V Value](ctx context.Context, q Query, qr Querier, inters []Interceptor) (v V, err error) { + for i := len(inters) - 1; i >= 0; i-- { + qr = inters[i].Intercept(qr) + } + rv, err := qr.Query(ctx, q) + if err != nil { + return v, err + } + vt, ok := rv.(V) + if !ok { + return v, fmt.Errorf("unexpected type %T returned from %T. expected type: %T", vt, q, v) + } + return vt, nil +} + +func scanWithInterceptors[Q1 ent.Query, Q2 interface { + sqlScan(context.Context, Q1, any) error +}](ctx context.Context, rootQuery Q1, selectOrGroup Q2, inters []Interceptor, v any) error { + rv := reflect.ValueOf(v) + var qr Querier = QuerierFunc(func(ctx context.Context, q Query) (Value, error) { + query, ok := q.(Q1) + if !ok { + return nil, fmt.Errorf("unexpected query type %T", q) + } + if err := selectOrGroup.sqlScan(ctx, query, v); err != nil { + return nil, err + } + if k := rv.Kind(); k == reflect.Pointer && rv.Elem().CanInterface() { + return rv.Elem().Interface(), nil + } + return v, nil + }) + for i := len(inters) - 1; i >= 0; i-- { + qr = inters[i].Intercept(qr) + } + vv, err := qr.Query(ctx, rootQuery) + if err != nil { + return err + } + switch rv2 := reflect.ValueOf(vv); { + case rv.IsNil(), rv2.IsNil(), rv.Kind() != reflect.Pointer: + case rv.Type() == rv2.Type(): + rv.Elem().Set(rv2.Elem()) + case rv.Elem().Type() == rv2.Type(): + rv.Elem().Set(rv2) + } + return nil +} + +// queryHook describes an internal hook for the different sqlAll methods. +type queryHook func(context.Context, *sqlgraph.QuerySpec) diff --git a/ent/enttest/enttest.go b/ent/enttest/enttest.go new file mode 100644 index 0000000..bfedcd1 --- /dev/null +++ b/ent/enttest/enttest.go @@ -0,0 +1,84 @@ +// Code generated by ent, DO NOT EDIT. + +package enttest + +import ( + "context" + + "github.com/stackmon/otc-status-dashboard/ent" + // required by schema hooks. + _ "github.com/stackmon/otc-status-dashboard/ent/runtime" + + "entgo.io/ent/dialect/sql/schema" + "github.com/stackmon/otc-status-dashboard/ent/migrate" +) + +type ( + // TestingT is the interface that is shared between + // testing.T and testing.B and used by enttest. + TestingT interface { + FailNow() + Error(...any) + } + + // Option configures client creation. + Option func(*options) + + options struct { + opts []ent.Option + migrateOpts []schema.MigrateOption + } +) + +// WithOptions forwards options to client creation. +func WithOptions(opts ...ent.Option) Option { + return func(o *options) { + o.opts = append(o.opts, opts...) + } +} + +// WithMigrateOptions forwards options to auto migration. +func WithMigrateOptions(opts ...schema.MigrateOption) Option { + return func(o *options) { + o.migrateOpts = append(o.migrateOpts, opts...) + } +} + +func newOptions(opts []Option) *options { + o := &options{} + for _, opt := range opts { + opt(o) + } + return o +} + +// Open calls ent.Open and auto-run migration. +func Open(t TestingT, driverName, dataSourceName string, opts ...Option) *ent.Client { + o := newOptions(opts) + c, err := ent.Open(driverName, dataSourceName, o.opts...) + if err != nil { + t.Error(err) + t.FailNow() + } + migrateSchema(t, c, o) + return c +} + +// NewClient calls ent.NewClient and auto-run migration. +func NewClient(t TestingT, opts ...Option) *ent.Client { + o := newOptions(opts) + c := ent.NewClient(o.opts...) + migrateSchema(t, c, o) + return c +} +func migrateSchema(t TestingT, c *ent.Client, o *options) { + tables, err := schema.CopyTables(migrate.Tables) + if err != nil { + t.Error(err) + t.FailNow() + } + if err := migrate.Create(context.Background(), c.Schema, tables, o.migrateOpts...); err != nil { + t.Error(err) + t.FailNow() + } +} diff --git a/ent/generate.go b/ent/generate.go new file mode 100644 index 0000000..fa95bb8 --- /dev/null +++ b/ent/generate.go @@ -0,0 +1,9 @@ +package ent + +import ( + "entgo.io/ent/entc" +) + +//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert --feature sql/versioned-migration ./schema + +var _ = entc.Generate diff --git a/ent/hook/hook.go b/ent/hook/hook.go new file mode 100644 index 0000000..91e8d4f --- /dev/null +++ b/ent/hook/hook.go @@ -0,0 +1,247 @@ +// Code generated by ent, DO NOT EDIT. + +package hook + +import ( + "context" + "fmt" + + "github.com/stackmon/otc-status-dashboard/ent" +) + +// The ComponentFunc type is an adapter to allow the use of ordinary +// function as Component mutator. +type ComponentFunc func(context.Context, *ent.ComponentMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f ComponentFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.ComponentMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ComponentMutation", m) +} + +// The ComponentAttrFunc type is an adapter to allow the use of ordinary +// function as ComponentAttr mutator. +type ComponentAttrFunc func(context.Context, *ent.ComponentAttrMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f ComponentAttrFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.ComponentAttrMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ComponentAttrMutation", m) +} + +// The IncidentFunc type is an adapter to allow the use of ordinary +// function as Incident mutator. +type IncidentFunc func(context.Context, *ent.IncidentMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f IncidentFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.IncidentMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.IncidentMutation", m) +} + +// The IncidentStatusFunc type is an adapter to allow the use of ordinary +// function as IncidentStatus mutator. +type IncidentStatusFunc func(context.Context, *ent.IncidentStatusMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f IncidentStatusFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.IncidentStatusMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.IncidentStatusMutation", m) +} + +// The NotificationOutboxFunc type is an adapter to allow the use of ordinary +// function as NotificationOutbox mutator. +type NotificationOutboxFunc func(context.Context, *ent.NotificationOutboxMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f NotificationOutboxFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.NotificationOutboxMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.NotificationOutboxMutation", m) +} + +// Condition is a hook condition function. +type Condition func(context.Context, ent.Mutation) bool + +// And groups conditions with the AND operator. +func And(first, second Condition, rest ...Condition) Condition { + return func(ctx context.Context, m ent.Mutation) bool { + if !first(ctx, m) || !second(ctx, m) { + return false + } + for _, cond := range rest { + if !cond(ctx, m) { + return false + } + } + return true + } +} + +// Or groups conditions with the OR operator. +func Or(first, second Condition, rest ...Condition) Condition { + return func(ctx context.Context, m ent.Mutation) bool { + if first(ctx, m) || second(ctx, m) { + return true + } + for _, cond := range rest { + if cond(ctx, m) { + return true + } + } + return false + } +} + +// Not negates a given condition. +func Not(cond Condition) Condition { + return func(ctx context.Context, m ent.Mutation) bool { + return !cond(ctx, m) + } +} + +// HasOp is a condition testing mutation operation. +func HasOp(op ent.Op) Condition { + return func(_ context.Context, m ent.Mutation) bool { + return m.Op().Is(op) + } +} + +// HasAddedFields is a condition validating `.AddedField` on fields. +func HasAddedFields(field string, fields ...string) Condition { + return func(_ context.Context, m ent.Mutation) bool { + if _, exists := m.AddedField(field); !exists { + return false + } + for _, field := range fields { + if _, exists := m.AddedField(field); !exists { + return false + } + } + return true + } +} + +// HasClearedFields is a condition validating `.FieldCleared` on fields. +func HasClearedFields(field string, fields ...string) Condition { + return func(_ context.Context, m ent.Mutation) bool { + if exists := m.FieldCleared(field); !exists { + return false + } + for _, field := range fields { + if exists := m.FieldCleared(field); !exists { + return false + } + } + return true + } +} + +// HasFields is a condition validating `.Field` on fields. +func HasFields(field string, fields ...string) Condition { + return func(_ context.Context, m ent.Mutation) bool { + if _, exists := m.Field(field); !exists { + return false + } + for _, field := range fields { + if _, exists := m.Field(field); !exists { + return false + } + } + return true + } +} + +// If executes the given hook under condition. +// +// hook.If(ComputeAverage, And(HasFields(...), HasAddedFields(...))) +func If(hk ent.Hook, cond Condition) ent.Hook { + return func(next ent.Mutator) ent.Mutator { + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if cond(ctx, m) { + return hk(next).Mutate(ctx, m) + } + return next.Mutate(ctx, m) + }) + } +} + +// On executes the given hook only for the given operation. +// +// hook.On(Log, ent.Delete|ent.Create) +func On(hk ent.Hook, op ent.Op) ent.Hook { + return If(hk, HasOp(op)) +} + +// Unless skips the given hook only for the given operation. +// +// hook.Unless(Log, ent.Update|ent.UpdateOne) +func Unless(hk ent.Hook, op ent.Op) ent.Hook { + return If(hk, Not(HasOp(op))) +} + +// FixedError is a hook returning a fixed error. +func FixedError(err error) ent.Hook { + return func(ent.Mutator) ent.Mutator { + return ent.MutateFunc(func(context.Context, ent.Mutation) (ent.Value, error) { + return nil, err + }) + } +} + +// Reject returns a hook that rejects all operations that match op. +// +// func (T) Hooks() []ent.Hook { +// return []ent.Hook{ +// Reject(ent.Delete|ent.Update), +// } +// } +func Reject(op ent.Op) ent.Hook { + hk := FixedError(fmt.Errorf("%s operation is not allowed", op)) + return On(hk, op) +} + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(mutator ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + mutator = c.hooks[i](mutator) + } + return mutator + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/ent/incident.go b/ent/incident.go new file mode 100644 index 0000000..6ea762d --- /dev/null +++ b/ent/incident.go @@ -0,0 +1,293 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/stackmon/otc-status-dashboard/ent/incident" +) + +// Incident is the model entity for the Incident schema. +type Incident struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Text holds the value of the "text" field. + Text string `json:"text,omitempty"` + // Description holds the value of the "description" field. + Description string `json:"description,omitempty"` + // StartDate holds the value of the "start_date" field. + StartDate time.Time `json:"start_date,omitempty"` + // EndDate holds the value of the "end_date" field. + EndDate time.Time `json:"end_date,omitempty"` + // Impact holds the value of the "impact" field. + Impact int `json:"impact,omitempty"` + // System holds the value of the "system" field. + System bool `json:"system,omitempty"` + // Type holds the value of the "type" field. + Type incident.Type `json:"type,omitempty"` + // Status holds the value of the "status" field. + Status string `json:"status,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // ModifiedAt holds the value of the "modified_at" field. + ModifiedAt time.Time `json:"modified_at,omitempty"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt time.Time `json:"deleted_at,omitempty"` + // CreatedBy holds the value of the "created_by" field. + CreatedBy string `json:"created_by,omitempty"` + // ContactEmail holds the value of the "contact_email" field. + ContactEmail string `json:"contact_email,omitempty"` + // Version holds the value of the "version" field. + Version int `json:"version,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the IncidentQuery when eager-loading is set. + Edges IncidentEdges `json:"edges"` + selectValues sql.SelectValues +} + +// IncidentEdges holds the relations/edges for other nodes in the graph. +type IncidentEdges struct { + // Components holds the value of the components edge. + Components []*Component `json:"components,omitempty"` + // Notifications holds the value of the notifications edge. + Notifications []*NotificationOutbox `json:"notifications,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [2]bool +} + +// ComponentsOrErr returns the Components value or an error if the edge +// was not loaded in eager-loading. +func (e IncidentEdges) ComponentsOrErr() ([]*Component, error) { + if e.loadedTypes[0] { + return e.Components, nil + } + return nil, &NotLoadedError{edge: "components"} +} + +// NotificationsOrErr returns the Notifications value or an error if the edge +// was not loaded in eager-loading. +func (e IncidentEdges) NotificationsOrErr() ([]*NotificationOutbox, error) { + if e.loadedTypes[1] { + return e.Notifications, nil + } + return nil, &NotLoadedError{edge: "notifications"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Incident) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case incident.FieldSystem: + values[i] = new(sql.NullBool) + case incident.FieldID, incident.FieldImpact, incident.FieldVersion: + values[i] = new(sql.NullInt64) + case incident.FieldText, incident.FieldDescription, incident.FieldType, incident.FieldStatus, incident.FieldCreatedBy, incident.FieldContactEmail: + values[i] = new(sql.NullString) + case incident.FieldStartDate, incident.FieldEndDate, incident.FieldCreatedAt, incident.FieldModifiedAt, incident.FieldDeletedAt: + values[i] = new(sql.NullTime) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Incident fields. +func (_m *Incident) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case incident.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + _m.ID = int(value.Int64) + case incident.FieldText: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field text", values[i]) + } else if value.Valid { + _m.Text = value.String + } + case incident.FieldDescription: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field description", values[i]) + } else if value.Valid { + _m.Description = value.String + } + case incident.FieldStartDate: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field start_date", values[i]) + } else if value.Valid { + _m.StartDate = value.Time + } + case incident.FieldEndDate: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field end_date", values[i]) + } else if value.Valid { + _m.EndDate = value.Time + } + case incident.FieldImpact: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field impact", values[i]) + } else if value.Valid { + _m.Impact = int(value.Int64) + } + case incident.FieldSystem: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field system", values[i]) + } else if value.Valid { + _m.System = value.Bool + } + case incident.FieldType: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field type", values[i]) + } else if value.Valid { + _m.Type = incident.Type(value.String) + } + case incident.FieldStatus: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field status", values[i]) + } else if value.Valid { + _m.Status = value.String + } + case incident.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + _m.CreatedAt = value.Time + } + case incident.FieldModifiedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field modified_at", values[i]) + } else if value.Valid { + _m.ModifiedAt = value.Time + } + case incident.FieldDeletedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value.Valid { + _m.DeletedAt = value.Time + } + case incident.FieldCreatedBy: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field created_by", values[i]) + } else if value.Valid { + _m.CreatedBy = value.String + } + case incident.FieldContactEmail: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field contact_email", values[i]) + } else if value.Valid { + _m.ContactEmail = value.String + } + case incident.FieldVersion: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field version", values[i]) + } else if value.Valid { + _m.Version = int(value.Int64) + } + default: + _m.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the Incident. +// This includes values selected through modifiers, order, etc. +func (_m *Incident) Value(name string) (ent.Value, error) { + return _m.selectValues.Get(name) +} + +// QueryComponents queries the "components" edge of the Incident entity. +func (_m *Incident) QueryComponents() *ComponentQuery { + return NewIncidentClient(_m.config).QueryComponents(_m) +} + +// QueryNotifications queries the "notifications" edge of the Incident entity. +func (_m *Incident) QueryNotifications() *NotificationOutboxQuery { + return NewIncidentClient(_m.config).QueryNotifications(_m) +} + +// Update returns a builder for updating this Incident. +// Note that you need to call Incident.Unwrap() before calling this method if this Incident +// was returned from a transaction, and the transaction was committed or rolled back. +func (_m *Incident) Update() *IncidentUpdateOne { + return NewIncidentClient(_m.config).UpdateOne(_m) +} + +// Unwrap unwraps the Incident entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (_m *Incident) Unwrap() *Incident { + _tx, ok := _m.config.driver.(*txDriver) + if !ok { + panic("ent: Incident is not a transactional entity") + } + _m.config.driver = _tx.drv + return _m +} + +// String implements the fmt.Stringer. +func (_m *Incident) String() string { + var builder strings.Builder + builder.WriteString("Incident(") + builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID)) + builder.WriteString("text=") + builder.WriteString(_m.Text) + builder.WriteString(", ") + builder.WriteString("description=") + builder.WriteString(_m.Description) + builder.WriteString(", ") + builder.WriteString("start_date=") + builder.WriteString(_m.StartDate.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("end_date=") + builder.WriteString(_m.EndDate.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("impact=") + builder.WriteString(fmt.Sprintf("%v", _m.Impact)) + builder.WriteString(", ") + builder.WriteString("system=") + builder.WriteString(fmt.Sprintf("%v", _m.System)) + builder.WriteString(", ") + builder.WriteString("type=") + builder.WriteString(fmt.Sprintf("%v", _m.Type)) + builder.WriteString(", ") + builder.WriteString("status=") + builder.WriteString(_m.Status) + builder.WriteString(", ") + builder.WriteString("created_at=") + builder.WriteString(_m.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("modified_at=") + builder.WriteString(_m.ModifiedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("deleted_at=") + builder.WriteString(_m.DeletedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("created_by=") + builder.WriteString(_m.CreatedBy) + builder.WriteString(", ") + builder.WriteString("contact_email=") + builder.WriteString(_m.ContactEmail) + builder.WriteString(", ") + builder.WriteString("version=") + builder.WriteString(fmt.Sprintf("%v", _m.Version)) + builder.WriteByte(')') + return builder.String() +} + +// Incidents is a parsable slice of Incident. +type Incidents []*Incident diff --git a/ent/incident/incident.go b/ent/incident/incident.go new file mode 100644 index 0000000..3f0b29f --- /dev/null +++ b/ent/incident/incident.go @@ -0,0 +1,251 @@ +// Code generated by ent, DO NOT EDIT. + +package incident + +import ( + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the incident type in the database. + Label = "incident" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldText holds the string denoting the text field in the database. + FieldText = "text" + // FieldDescription holds the string denoting the description field in the database. + FieldDescription = "description" + // FieldStartDate holds the string denoting the start_date field in the database. + FieldStartDate = "start_date" + // FieldEndDate holds the string denoting the end_date field in the database. + FieldEndDate = "end_date" + // FieldImpact holds the string denoting the impact field in the database. + FieldImpact = "impact" + // FieldSystem holds the string denoting the system field in the database. + FieldSystem = "system" + // FieldType holds the string denoting the type field in the database. + FieldType = "type" + // FieldStatus holds the string denoting the status field in the database. + FieldStatus = "status" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldModifiedAt holds the string denoting the modified_at field in the database. + FieldModifiedAt = "modified_at" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // FieldCreatedBy holds the string denoting the created_by field in the database. + FieldCreatedBy = "created_by" + // FieldContactEmail holds the string denoting the contact_email field in the database. + FieldContactEmail = "contact_email" + // FieldVersion holds the string denoting the version field in the database. + FieldVersion = "version" + // EdgeComponents holds the string denoting the components edge name in mutations. + EdgeComponents = "components" + // EdgeNotifications holds the string denoting the notifications edge name in mutations. + EdgeNotifications = "notifications" + // Table holds the table name of the incident in the database. + Table = "incident" + // ComponentsTable is the table that holds the components relation/edge. The primary key declared below. + ComponentsTable = "incident_component_relation" + // ComponentsInverseTable is the table name for the Component entity. + // It exists in this package in order to avoid circular dependency with the "component" package. + ComponentsInverseTable = "component" + // NotificationsTable is the table that holds the notifications relation/edge. + NotificationsTable = "notification_outbox" + // NotificationsInverseTable is the table name for the NotificationOutbox entity. + // It exists in this package in order to avoid circular dependency with the "notificationoutbox" package. + NotificationsInverseTable = "notification_outbox" + // NotificationsColumn is the table column denoting the notifications relation/edge. + NotificationsColumn = "incident_id" +) + +// Columns holds all SQL columns for incident fields. +var Columns = []string{ + FieldID, + FieldText, + FieldDescription, + FieldStartDate, + FieldEndDate, + FieldImpact, + FieldSystem, + FieldType, + FieldStatus, + FieldCreatedAt, + FieldModifiedAt, + FieldDeletedAt, + FieldCreatedBy, + FieldContactEmail, + FieldVersion, +} + +var ( + // ComponentsPrimaryKey and ComponentsColumn2 are the table columns denoting the + // primary key for the components relation (M2M). + ComponentsPrimaryKey = []string{"incident_id", "component_id"} +) + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // TextValidator is a validator for the "text" field. It is called by the builders before save. + TextValidator func(string) error + // DefaultSystem holds the default value on creation for the "system" field. + DefaultSystem bool + // DefaultVersion holds the default value on creation for the "version" field. + DefaultVersion int +) + +// Type defines the type for the "type" enum field. +type Type string + +// Type values. +const ( + TypeIncident Type = "incident" + TypeInfo Type = "info" + TypeMaintenance Type = "maintenance" +) + +func (_type Type) String() string { + return string(_type) +} + +// TypeValidator is a validator for the "type" field enum values. It is called by the builders before save. +func TypeValidator(_type Type) error { + switch _type { + case TypeIncident, TypeInfo, TypeMaintenance: + return nil + default: + return fmt.Errorf("incident: invalid enum value for type field: %q", _type) + } +} + +// OrderOption defines the ordering options for the Incident queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByText orders the results by the text field. +func ByText(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldText, opts...).ToFunc() +} + +// ByDescription orders the results by the description field. +func ByDescription(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDescription, opts...).ToFunc() +} + +// ByStartDate orders the results by the start_date field. +func ByStartDate(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldStartDate, opts...).ToFunc() +} + +// ByEndDate orders the results by the end_date field. +func ByEndDate(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldEndDate, opts...).ToFunc() +} + +// ByImpact orders the results by the impact field. +func ByImpact(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldImpact, opts...).ToFunc() +} + +// BySystem orders the results by the system field. +func BySystem(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldSystem, opts...).ToFunc() +} + +// ByType orders the results by the type field. +func ByType(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldType, opts...).ToFunc() +} + +// ByStatus orders the results by the status field. +func ByStatus(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldStatus, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByModifiedAt orders the results by the modified_at field. +func ByModifiedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldModifiedAt, opts...).ToFunc() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByCreatedBy orders the results by the created_by field. +func ByCreatedBy(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedBy, opts...).ToFunc() +} + +// ByContactEmail orders the results by the contact_email field. +func ByContactEmail(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldContactEmail, opts...).ToFunc() +} + +// ByVersion orders the results by the version field. +func ByVersion(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldVersion, opts...).ToFunc() +} + +// ByComponentsCount orders the results by components count. +func ByComponentsCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newComponentsStep(), opts...) + } +} + +// ByComponents orders the results by components terms. +func ByComponents(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newComponentsStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} + +// ByNotificationsCount orders the results by notifications count. +func ByNotificationsCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newNotificationsStep(), opts...) + } +} + +// ByNotifications orders the results by notifications terms. +func ByNotifications(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newNotificationsStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} +func newComponentsStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ComponentsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, ComponentsTable, ComponentsPrimaryKey...), + ) +} +func newNotificationsStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(NotificationsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, NotificationsTable, NotificationsColumn), + ) +} diff --git a/ent/incident/where.go b/ent/incident/where.go new file mode 100644 index 0000000..e123223 --- /dev/null +++ b/ent/incident/where.go @@ -0,0 +1,897 @@ +// Code generated by ent, DO NOT EDIT. + +package incident + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldID, id)) +} + +// Text applies equality check predicate on the "text" field. It's identical to TextEQ. +func Text(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldText, v)) +} + +// Description applies equality check predicate on the "description" field. It's identical to DescriptionEQ. +func Description(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldDescription, v)) +} + +// StartDate applies equality check predicate on the "start_date" field. It's identical to StartDateEQ. +func StartDate(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldStartDate, v)) +} + +// EndDate applies equality check predicate on the "end_date" field. It's identical to EndDateEQ. +func EndDate(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldEndDate, v)) +} + +// Impact applies equality check predicate on the "impact" field. It's identical to ImpactEQ. +func Impact(v int) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldImpact, v)) +} + +// System applies equality check predicate on the "system" field. It's identical to SystemEQ. +func System(v bool) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldSystem, v)) +} + +// Status applies equality check predicate on the "status" field. It's identical to StatusEQ. +func Status(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldStatus, v)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldCreatedAt, v)) +} + +// ModifiedAt applies equality check predicate on the "modified_at" field. It's identical to ModifiedAtEQ. +func ModifiedAt(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldModifiedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldDeletedAt, v)) +} + +// CreatedBy applies equality check predicate on the "created_by" field. It's identical to CreatedByEQ. +func CreatedBy(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldCreatedBy, v)) +} + +// ContactEmail applies equality check predicate on the "contact_email" field. It's identical to ContactEmailEQ. +func ContactEmail(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldContactEmail, v)) +} + +// Version applies equality check predicate on the "version" field. It's identical to VersionEQ. +func Version(v int) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldVersion, v)) +} + +// TextEQ applies the EQ predicate on the "text" field. +func TextEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldText, v)) +} + +// TextNEQ applies the NEQ predicate on the "text" field. +func TextNEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldText, v)) +} + +// TextIn applies the In predicate on the "text" field. +func TextIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldText, vs...)) +} + +// TextNotIn applies the NotIn predicate on the "text" field. +func TextNotIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldText, vs...)) +} + +// TextGT applies the GT predicate on the "text" field. +func TextGT(v string) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldText, v)) +} + +// TextGTE applies the GTE predicate on the "text" field. +func TextGTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldText, v)) +} + +// TextLT applies the LT predicate on the "text" field. +func TextLT(v string) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldText, v)) +} + +// TextLTE applies the LTE predicate on the "text" field. +func TextLTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldText, v)) +} + +// TextContains applies the Contains predicate on the "text" field. +func TextContains(v string) predicate.Incident { + return predicate.Incident(sql.FieldContains(FieldText, v)) +} + +// TextHasPrefix applies the HasPrefix predicate on the "text" field. +func TextHasPrefix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasPrefix(FieldText, v)) +} + +// TextHasSuffix applies the HasSuffix predicate on the "text" field. +func TextHasSuffix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasSuffix(FieldText, v)) +} + +// TextEqualFold applies the EqualFold predicate on the "text" field. +func TextEqualFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldEqualFold(FieldText, v)) +} + +// TextContainsFold applies the ContainsFold predicate on the "text" field. +func TextContainsFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldContainsFold(FieldText, v)) +} + +// DescriptionEQ applies the EQ predicate on the "description" field. +func DescriptionEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldDescription, v)) +} + +// DescriptionNEQ applies the NEQ predicate on the "description" field. +func DescriptionNEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldDescription, v)) +} + +// DescriptionIn applies the In predicate on the "description" field. +func DescriptionIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldDescription, vs...)) +} + +// DescriptionNotIn applies the NotIn predicate on the "description" field. +func DescriptionNotIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldDescription, vs...)) +} + +// DescriptionGT applies the GT predicate on the "description" field. +func DescriptionGT(v string) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldDescription, v)) +} + +// DescriptionGTE applies the GTE predicate on the "description" field. +func DescriptionGTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldDescription, v)) +} + +// DescriptionLT applies the LT predicate on the "description" field. +func DescriptionLT(v string) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldDescription, v)) +} + +// DescriptionLTE applies the LTE predicate on the "description" field. +func DescriptionLTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldDescription, v)) +} + +// DescriptionContains applies the Contains predicate on the "description" field. +func DescriptionContains(v string) predicate.Incident { + return predicate.Incident(sql.FieldContains(FieldDescription, v)) +} + +// DescriptionHasPrefix applies the HasPrefix predicate on the "description" field. +func DescriptionHasPrefix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasPrefix(FieldDescription, v)) +} + +// DescriptionHasSuffix applies the HasSuffix predicate on the "description" field. +func DescriptionHasSuffix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasSuffix(FieldDescription, v)) +} + +// DescriptionIsNil applies the IsNil predicate on the "description" field. +func DescriptionIsNil() predicate.Incident { + return predicate.Incident(sql.FieldIsNull(FieldDescription)) +} + +// DescriptionNotNil applies the NotNil predicate on the "description" field. +func DescriptionNotNil() predicate.Incident { + return predicate.Incident(sql.FieldNotNull(FieldDescription)) +} + +// DescriptionEqualFold applies the EqualFold predicate on the "description" field. +func DescriptionEqualFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldEqualFold(FieldDescription, v)) +} + +// DescriptionContainsFold applies the ContainsFold predicate on the "description" field. +func DescriptionContainsFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldContainsFold(FieldDescription, v)) +} + +// StartDateEQ applies the EQ predicate on the "start_date" field. +func StartDateEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldStartDate, v)) +} + +// StartDateNEQ applies the NEQ predicate on the "start_date" field. +func StartDateNEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldStartDate, v)) +} + +// StartDateIn applies the In predicate on the "start_date" field. +func StartDateIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldStartDate, vs...)) +} + +// StartDateNotIn applies the NotIn predicate on the "start_date" field. +func StartDateNotIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldStartDate, vs...)) +} + +// StartDateGT applies the GT predicate on the "start_date" field. +func StartDateGT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldStartDate, v)) +} + +// StartDateGTE applies the GTE predicate on the "start_date" field. +func StartDateGTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldStartDate, v)) +} + +// StartDateLT applies the LT predicate on the "start_date" field. +func StartDateLT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldStartDate, v)) +} + +// StartDateLTE applies the LTE predicate on the "start_date" field. +func StartDateLTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldStartDate, v)) +} + +// EndDateEQ applies the EQ predicate on the "end_date" field. +func EndDateEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldEndDate, v)) +} + +// EndDateNEQ applies the NEQ predicate on the "end_date" field. +func EndDateNEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldEndDate, v)) +} + +// EndDateIn applies the In predicate on the "end_date" field. +func EndDateIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldEndDate, vs...)) +} + +// EndDateNotIn applies the NotIn predicate on the "end_date" field. +func EndDateNotIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldEndDate, vs...)) +} + +// EndDateGT applies the GT predicate on the "end_date" field. +func EndDateGT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldEndDate, v)) +} + +// EndDateGTE applies the GTE predicate on the "end_date" field. +func EndDateGTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldEndDate, v)) +} + +// EndDateLT applies the LT predicate on the "end_date" field. +func EndDateLT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldEndDate, v)) +} + +// EndDateLTE applies the LTE predicate on the "end_date" field. +func EndDateLTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldEndDate, v)) +} + +// EndDateIsNil applies the IsNil predicate on the "end_date" field. +func EndDateIsNil() predicate.Incident { + return predicate.Incident(sql.FieldIsNull(FieldEndDate)) +} + +// EndDateNotNil applies the NotNil predicate on the "end_date" field. +func EndDateNotNil() predicate.Incident { + return predicate.Incident(sql.FieldNotNull(FieldEndDate)) +} + +// ImpactEQ applies the EQ predicate on the "impact" field. +func ImpactEQ(v int) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldImpact, v)) +} + +// ImpactNEQ applies the NEQ predicate on the "impact" field. +func ImpactNEQ(v int) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldImpact, v)) +} + +// ImpactIn applies the In predicate on the "impact" field. +func ImpactIn(vs ...int) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldImpact, vs...)) +} + +// ImpactNotIn applies the NotIn predicate on the "impact" field. +func ImpactNotIn(vs ...int) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldImpact, vs...)) +} + +// ImpactGT applies the GT predicate on the "impact" field. +func ImpactGT(v int) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldImpact, v)) +} + +// ImpactGTE applies the GTE predicate on the "impact" field. +func ImpactGTE(v int) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldImpact, v)) +} + +// ImpactLT applies the LT predicate on the "impact" field. +func ImpactLT(v int) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldImpact, v)) +} + +// ImpactLTE applies the LTE predicate on the "impact" field. +func ImpactLTE(v int) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldImpact, v)) +} + +// SystemEQ applies the EQ predicate on the "system" field. +func SystemEQ(v bool) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldSystem, v)) +} + +// SystemNEQ applies the NEQ predicate on the "system" field. +func SystemNEQ(v bool) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldSystem, v)) +} + +// TypeEQ applies the EQ predicate on the "type" field. +func TypeEQ(v Type) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldType, v)) +} + +// TypeNEQ applies the NEQ predicate on the "type" field. +func TypeNEQ(v Type) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldType, v)) +} + +// TypeIn applies the In predicate on the "type" field. +func TypeIn(vs ...Type) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldType, vs...)) +} + +// TypeNotIn applies the NotIn predicate on the "type" field. +func TypeNotIn(vs ...Type) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldType, vs...)) +} + +// StatusEQ applies the EQ predicate on the "status" field. +func StatusEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldStatus, v)) +} + +// StatusNEQ applies the NEQ predicate on the "status" field. +func StatusNEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldStatus, v)) +} + +// StatusIn applies the In predicate on the "status" field. +func StatusIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldStatus, vs...)) +} + +// StatusNotIn applies the NotIn predicate on the "status" field. +func StatusNotIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldStatus, vs...)) +} + +// StatusGT applies the GT predicate on the "status" field. +func StatusGT(v string) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldStatus, v)) +} + +// StatusGTE applies the GTE predicate on the "status" field. +func StatusGTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldStatus, v)) +} + +// StatusLT applies the LT predicate on the "status" field. +func StatusLT(v string) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldStatus, v)) +} + +// StatusLTE applies the LTE predicate on the "status" field. +func StatusLTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldStatus, v)) +} + +// StatusContains applies the Contains predicate on the "status" field. +func StatusContains(v string) predicate.Incident { + return predicate.Incident(sql.FieldContains(FieldStatus, v)) +} + +// StatusHasPrefix applies the HasPrefix predicate on the "status" field. +func StatusHasPrefix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasPrefix(FieldStatus, v)) +} + +// StatusHasSuffix applies the HasSuffix predicate on the "status" field. +func StatusHasSuffix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasSuffix(FieldStatus, v)) +} + +// StatusIsNil applies the IsNil predicate on the "status" field. +func StatusIsNil() predicate.Incident { + return predicate.Incident(sql.FieldIsNull(FieldStatus)) +} + +// StatusNotNil applies the NotNil predicate on the "status" field. +func StatusNotNil() predicate.Incident { + return predicate.Incident(sql.FieldNotNull(FieldStatus)) +} + +// StatusEqualFold applies the EqualFold predicate on the "status" field. +func StatusEqualFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldEqualFold(FieldStatus, v)) +} + +// StatusContainsFold applies the ContainsFold predicate on the "status" field. +func StatusContainsFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldContainsFold(FieldStatus, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldCreatedAt, v)) +} + +// CreatedAtIsNil applies the IsNil predicate on the "created_at" field. +func CreatedAtIsNil() predicate.Incident { + return predicate.Incident(sql.FieldIsNull(FieldCreatedAt)) +} + +// CreatedAtNotNil applies the NotNil predicate on the "created_at" field. +func CreatedAtNotNil() predicate.Incident { + return predicate.Incident(sql.FieldNotNull(FieldCreatedAt)) +} + +// ModifiedAtEQ applies the EQ predicate on the "modified_at" field. +func ModifiedAtEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldModifiedAt, v)) +} + +// ModifiedAtNEQ applies the NEQ predicate on the "modified_at" field. +func ModifiedAtNEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldModifiedAt, v)) +} + +// ModifiedAtIn applies the In predicate on the "modified_at" field. +func ModifiedAtIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldModifiedAt, vs...)) +} + +// ModifiedAtNotIn applies the NotIn predicate on the "modified_at" field. +func ModifiedAtNotIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldModifiedAt, vs...)) +} + +// ModifiedAtGT applies the GT predicate on the "modified_at" field. +func ModifiedAtGT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldModifiedAt, v)) +} + +// ModifiedAtGTE applies the GTE predicate on the "modified_at" field. +func ModifiedAtGTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldModifiedAt, v)) +} + +// ModifiedAtLT applies the LT predicate on the "modified_at" field. +func ModifiedAtLT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldModifiedAt, v)) +} + +// ModifiedAtLTE applies the LTE predicate on the "modified_at" field. +func ModifiedAtLTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldModifiedAt, v)) +} + +// ModifiedAtIsNil applies the IsNil predicate on the "modified_at" field. +func ModifiedAtIsNil() predicate.Incident { + return predicate.Incident(sql.FieldIsNull(FieldModifiedAt)) +} + +// ModifiedAtNotNil applies the NotNil predicate on the "modified_at" field. +func ModifiedAtNotNil() predicate.Incident { + return predicate.Incident(sql.FieldNotNull(FieldModifiedAt)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...time.Time) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v time.Time) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.Incident { + return predicate.Incident(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.Incident { + return predicate.Incident(sql.FieldNotNull(FieldDeletedAt)) +} + +// CreatedByEQ applies the EQ predicate on the "created_by" field. +func CreatedByEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldCreatedBy, v)) +} + +// CreatedByNEQ applies the NEQ predicate on the "created_by" field. +func CreatedByNEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldCreatedBy, v)) +} + +// CreatedByIn applies the In predicate on the "created_by" field. +func CreatedByIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldCreatedBy, vs...)) +} + +// CreatedByNotIn applies the NotIn predicate on the "created_by" field. +func CreatedByNotIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldCreatedBy, vs...)) +} + +// CreatedByGT applies the GT predicate on the "created_by" field. +func CreatedByGT(v string) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldCreatedBy, v)) +} + +// CreatedByGTE applies the GTE predicate on the "created_by" field. +func CreatedByGTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldCreatedBy, v)) +} + +// CreatedByLT applies the LT predicate on the "created_by" field. +func CreatedByLT(v string) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldCreatedBy, v)) +} + +// CreatedByLTE applies the LTE predicate on the "created_by" field. +func CreatedByLTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldCreatedBy, v)) +} + +// CreatedByContains applies the Contains predicate on the "created_by" field. +func CreatedByContains(v string) predicate.Incident { + return predicate.Incident(sql.FieldContains(FieldCreatedBy, v)) +} + +// CreatedByHasPrefix applies the HasPrefix predicate on the "created_by" field. +func CreatedByHasPrefix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasPrefix(FieldCreatedBy, v)) +} + +// CreatedByHasSuffix applies the HasSuffix predicate on the "created_by" field. +func CreatedByHasSuffix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasSuffix(FieldCreatedBy, v)) +} + +// CreatedByIsNil applies the IsNil predicate on the "created_by" field. +func CreatedByIsNil() predicate.Incident { + return predicate.Incident(sql.FieldIsNull(FieldCreatedBy)) +} + +// CreatedByNotNil applies the NotNil predicate on the "created_by" field. +func CreatedByNotNil() predicate.Incident { + return predicate.Incident(sql.FieldNotNull(FieldCreatedBy)) +} + +// CreatedByEqualFold applies the EqualFold predicate on the "created_by" field. +func CreatedByEqualFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldEqualFold(FieldCreatedBy, v)) +} + +// CreatedByContainsFold applies the ContainsFold predicate on the "created_by" field. +func CreatedByContainsFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldContainsFold(FieldCreatedBy, v)) +} + +// ContactEmailEQ applies the EQ predicate on the "contact_email" field. +func ContactEmailEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldContactEmail, v)) +} + +// ContactEmailNEQ applies the NEQ predicate on the "contact_email" field. +func ContactEmailNEQ(v string) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldContactEmail, v)) +} + +// ContactEmailIn applies the In predicate on the "contact_email" field. +func ContactEmailIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldContactEmail, vs...)) +} + +// ContactEmailNotIn applies the NotIn predicate on the "contact_email" field. +func ContactEmailNotIn(vs ...string) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldContactEmail, vs...)) +} + +// ContactEmailGT applies the GT predicate on the "contact_email" field. +func ContactEmailGT(v string) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldContactEmail, v)) +} + +// ContactEmailGTE applies the GTE predicate on the "contact_email" field. +func ContactEmailGTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldContactEmail, v)) +} + +// ContactEmailLT applies the LT predicate on the "contact_email" field. +func ContactEmailLT(v string) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldContactEmail, v)) +} + +// ContactEmailLTE applies the LTE predicate on the "contact_email" field. +func ContactEmailLTE(v string) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldContactEmail, v)) +} + +// ContactEmailContains applies the Contains predicate on the "contact_email" field. +func ContactEmailContains(v string) predicate.Incident { + return predicate.Incident(sql.FieldContains(FieldContactEmail, v)) +} + +// ContactEmailHasPrefix applies the HasPrefix predicate on the "contact_email" field. +func ContactEmailHasPrefix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasPrefix(FieldContactEmail, v)) +} + +// ContactEmailHasSuffix applies the HasSuffix predicate on the "contact_email" field. +func ContactEmailHasSuffix(v string) predicate.Incident { + return predicate.Incident(sql.FieldHasSuffix(FieldContactEmail, v)) +} + +// ContactEmailIsNil applies the IsNil predicate on the "contact_email" field. +func ContactEmailIsNil() predicate.Incident { + return predicate.Incident(sql.FieldIsNull(FieldContactEmail)) +} + +// ContactEmailNotNil applies the NotNil predicate on the "contact_email" field. +func ContactEmailNotNil() predicate.Incident { + return predicate.Incident(sql.FieldNotNull(FieldContactEmail)) +} + +// ContactEmailEqualFold applies the EqualFold predicate on the "contact_email" field. +func ContactEmailEqualFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldEqualFold(FieldContactEmail, v)) +} + +// ContactEmailContainsFold applies the ContainsFold predicate on the "contact_email" field. +func ContactEmailContainsFold(v string) predicate.Incident { + return predicate.Incident(sql.FieldContainsFold(FieldContactEmail, v)) +} + +// VersionEQ applies the EQ predicate on the "version" field. +func VersionEQ(v int) predicate.Incident { + return predicate.Incident(sql.FieldEQ(FieldVersion, v)) +} + +// VersionNEQ applies the NEQ predicate on the "version" field. +func VersionNEQ(v int) predicate.Incident { + return predicate.Incident(sql.FieldNEQ(FieldVersion, v)) +} + +// VersionIn applies the In predicate on the "version" field. +func VersionIn(vs ...int) predicate.Incident { + return predicate.Incident(sql.FieldIn(FieldVersion, vs...)) +} + +// VersionNotIn applies the NotIn predicate on the "version" field. +func VersionNotIn(vs ...int) predicate.Incident { + return predicate.Incident(sql.FieldNotIn(FieldVersion, vs...)) +} + +// VersionGT applies the GT predicate on the "version" field. +func VersionGT(v int) predicate.Incident { + return predicate.Incident(sql.FieldGT(FieldVersion, v)) +} + +// VersionGTE applies the GTE predicate on the "version" field. +func VersionGTE(v int) predicate.Incident { + return predicate.Incident(sql.FieldGTE(FieldVersion, v)) +} + +// VersionLT applies the LT predicate on the "version" field. +func VersionLT(v int) predicate.Incident { + return predicate.Incident(sql.FieldLT(FieldVersion, v)) +} + +// VersionLTE applies the LTE predicate on the "version" field. +func VersionLTE(v int) predicate.Incident { + return predicate.Incident(sql.FieldLTE(FieldVersion, v)) +} + +// HasComponents applies the HasEdge predicate on the "components" edge. +func HasComponents() predicate.Incident { + return predicate.Incident(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, ComponentsTable, ComponentsPrimaryKey...), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasComponentsWith applies the HasEdge predicate on the "components" edge with a given conditions (other predicates). +func HasComponentsWith(preds ...predicate.Component) predicate.Incident { + return predicate.Incident(func(s *sql.Selector) { + step := newComponentsStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasNotifications applies the HasEdge predicate on the "notifications" edge. +func HasNotifications() predicate.Incident { + return predicate.Incident(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, NotificationsTable, NotificationsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasNotificationsWith applies the HasEdge predicate on the "notifications" edge with a given conditions (other predicates). +func HasNotificationsWith(preds ...predicate.NotificationOutbox) predicate.Incident { + return predicate.Incident(func(s *sql.Selector) { + step := newNotificationsStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Incident) predicate.Incident { + return predicate.Incident(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Incident) predicate.Incident { + return predicate.Incident(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Incident) predicate.Incident { + return predicate.Incident(sql.NotPredicates(p)) +} diff --git a/ent/incident_create.go b/ent/incident_create.go new file mode 100644 index 0000000..b0164d2 --- /dev/null +++ b/ent/incident_create.go @@ -0,0 +1,1518 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" +) + +// IncidentCreate is the builder for creating a Incident entity. +type IncidentCreate struct { + config + mutation *IncidentMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetText sets the "text" field. +func (_c *IncidentCreate) SetText(v string) *IncidentCreate { + _c.mutation.SetText(v) + return _c +} + +// SetDescription sets the "description" field. +func (_c *IncidentCreate) SetDescription(v string) *IncidentCreate { + _c.mutation.SetDescription(v) + return _c +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableDescription(v *string) *IncidentCreate { + if v != nil { + _c.SetDescription(*v) + } + return _c +} + +// SetStartDate sets the "start_date" field. +func (_c *IncidentCreate) SetStartDate(v time.Time) *IncidentCreate { + _c.mutation.SetStartDate(v) + return _c +} + +// SetEndDate sets the "end_date" field. +func (_c *IncidentCreate) SetEndDate(v time.Time) *IncidentCreate { + _c.mutation.SetEndDate(v) + return _c +} + +// SetNillableEndDate sets the "end_date" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableEndDate(v *time.Time) *IncidentCreate { + if v != nil { + _c.SetEndDate(*v) + } + return _c +} + +// SetImpact sets the "impact" field. +func (_c *IncidentCreate) SetImpact(v int) *IncidentCreate { + _c.mutation.SetImpact(v) + return _c +} + +// SetSystem sets the "system" field. +func (_c *IncidentCreate) SetSystem(v bool) *IncidentCreate { + _c.mutation.SetSystem(v) + return _c +} + +// SetNillableSystem sets the "system" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableSystem(v *bool) *IncidentCreate { + if v != nil { + _c.SetSystem(*v) + } + return _c +} + +// SetType sets the "type" field. +func (_c *IncidentCreate) SetType(v incident.Type) *IncidentCreate { + _c.mutation.SetType(v) + return _c +} + +// SetStatus sets the "status" field. +func (_c *IncidentCreate) SetStatus(v string) *IncidentCreate { + _c.mutation.SetStatus(v) + return _c +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableStatus(v *string) *IncidentCreate { + if v != nil { + _c.SetStatus(*v) + } + return _c +} + +// SetCreatedAt sets the "created_at" field. +func (_c *IncidentCreate) SetCreatedAt(v time.Time) *IncidentCreate { + _c.mutation.SetCreatedAt(v) + return _c +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableCreatedAt(v *time.Time) *IncidentCreate { + if v != nil { + _c.SetCreatedAt(*v) + } + return _c +} + +// SetModifiedAt sets the "modified_at" field. +func (_c *IncidentCreate) SetModifiedAt(v time.Time) *IncidentCreate { + _c.mutation.SetModifiedAt(v) + return _c +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableModifiedAt(v *time.Time) *IncidentCreate { + if v != nil { + _c.SetModifiedAt(*v) + } + return _c +} + +// SetDeletedAt sets the "deleted_at" field. +func (_c *IncidentCreate) SetDeletedAt(v time.Time) *IncidentCreate { + _c.mutation.SetDeletedAt(v) + return _c +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableDeletedAt(v *time.Time) *IncidentCreate { + if v != nil { + _c.SetDeletedAt(*v) + } + return _c +} + +// SetCreatedBy sets the "created_by" field. +func (_c *IncidentCreate) SetCreatedBy(v string) *IncidentCreate { + _c.mutation.SetCreatedBy(v) + return _c +} + +// SetNillableCreatedBy sets the "created_by" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableCreatedBy(v *string) *IncidentCreate { + if v != nil { + _c.SetCreatedBy(*v) + } + return _c +} + +// SetContactEmail sets the "contact_email" field. +func (_c *IncidentCreate) SetContactEmail(v string) *IncidentCreate { + _c.mutation.SetContactEmail(v) + return _c +} + +// SetNillableContactEmail sets the "contact_email" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableContactEmail(v *string) *IncidentCreate { + if v != nil { + _c.SetContactEmail(*v) + } + return _c +} + +// SetVersion sets the "version" field. +func (_c *IncidentCreate) SetVersion(v int) *IncidentCreate { + _c.mutation.SetVersion(v) + return _c +} + +// SetNillableVersion sets the "version" field if the given value is not nil. +func (_c *IncidentCreate) SetNillableVersion(v *int) *IncidentCreate { + if v != nil { + _c.SetVersion(*v) + } + return _c +} + +// SetID sets the "id" field. +func (_c *IncidentCreate) SetID(v int) *IncidentCreate { + _c.mutation.SetID(v) + return _c +} + +// AddComponentIDs adds the "components" edge to the Component entity by IDs. +func (_c *IncidentCreate) AddComponentIDs(ids ...int) *IncidentCreate { + _c.mutation.AddComponentIDs(ids...) + return _c +} + +// AddComponents adds the "components" edges to the Component entity. +func (_c *IncidentCreate) AddComponents(v ...*Component) *IncidentCreate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _c.AddComponentIDs(ids...) +} + +// AddNotificationIDs adds the "notifications" edge to the NotificationOutbox entity by IDs. +func (_c *IncidentCreate) AddNotificationIDs(ids ...int) *IncidentCreate { + _c.mutation.AddNotificationIDs(ids...) + return _c +} + +// AddNotifications adds the "notifications" edges to the NotificationOutbox entity. +func (_c *IncidentCreate) AddNotifications(v ...*NotificationOutbox) *IncidentCreate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _c.AddNotificationIDs(ids...) +} + +// Mutation returns the IncidentMutation object of the builder. +func (_c *IncidentCreate) Mutation() *IncidentMutation { + return _c.mutation +} + +// Save creates the Incident in the database. +func (_c *IncidentCreate) Save(ctx context.Context) (*Incident, error) { + _c.defaults() + return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (_c *IncidentCreate) SaveX(ctx context.Context) *Incident { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *IncidentCreate) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *IncidentCreate) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (_c *IncidentCreate) defaults() { + if _, ok := _c.mutation.System(); !ok { + v := incident.DefaultSystem + _c.mutation.SetSystem(v) + } + if _, ok := _c.mutation.Version(); !ok { + v := incident.DefaultVersion + _c.mutation.SetVersion(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_c *IncidentCreate) check() error { + if _, ok := _c.mutation.Text(); !ok { + return &ValidationError{Name: "text", err: errors.New(`ent: missing required field "Incident.text"`)} + } + if v, ok := _c.mutation.Text(); ok { + if err := incident.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Incident.text": %w`, err)} + } + } + if _, ok := _c.mutation.StartDate(); !ok { + return &ValidationError{Name: "start_date", err: errors.New(`ent: missing required field "Incident.start_date"`)} + } + if _, ok := _c.mutation.Impact(); !ok { + return &ValidationError{Name: "impact", err: errors.New(`ent: missing required field "Incident.impact"`)} + } + if _, ok := _c.mutation.System(); !ok { + return &ValidationError{Name: "system", err: errors.New(`ent: missing required field "Incident.system"`)} + } + if _, ok := _c.mutation.GetType(); !ok { + return &ValidationError{Name: "type", err: errors.New(`ent: missing required field "Incident.type"`)} + } + if v, ok := _c.mutation.GetType(); ok { + if err := incident.TypeValidator(v); err != nil { + return &ValidationError{Name: "type", err: fmt.Errorf(`ent: validator failed for field "Incident.type": %w`, err)} + } + } + if _, ok := _c.mutation.Version(); !ok { + return &ValidationError{Name: "version", err: errors.New(`ent: missing required field "Incident.version"`)} + } + return nil +} + +func (_c *IncidentCreate) sqlSave(ctx context.Context) (*Incident, error) { + if err := _c.check(); err != nil { + return nil, err + } + _node, _spec := _c.createSpec() + if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int(id) + } + _c.mutation.id = &_node.ID + _c.mutation.done = true + return _node, nil +} + +func (_c *IncidentCreate) createSpec() (*Incident, *sqlgraph.CreateSpec) { + var ( + _node = &Incident{config: _c.config} + _spec = sqlgraph.NewCreateSpec(incident.Table, sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt)) + ) + _spec.OnConflict = _c.conflict + if id, ok := _c.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := _c.mutation.Text(); ok { + _spec.SetField(incident.FieldText, field.TypeString, value) + _node.Text = value + } + if value, ok := _c.mutation.Description(); ok { + _spec.SetField(incident.FieldDescription, field.TypeString, value) + _node.Description = value + } + if value, ok := _c.mutation.StartDate(); ok { + _spec.SetField(incident.FieldStartDate, field.TypeTime, value) + _node.StartDate = value + } + if value, ok := _c.mutation.EndDate(); ok { + _spec.SetField(incident.FieldEndDate, field.TypeTime, value) + _node.EndDate = value + } + if value, ok := _c.mutation.Impact(); ok { + _spec.SetField(incident.FieldImpact, field.TypeInt, value) + _node.Impact = value + } + if value, ok := _c.mutation.System(); ok { + _spec.SetField(incident.FieldSystem, field.TypeBool, value) + _node.System = value + } + if value, ok := _c.mutation.GetType(); ok { + _spec.SetField(incident.FieldType, field.TypeEnum, value) + _node.Type = value + } + if value, ok := _c.mutation.Status(); ok { + _spec.SetField(incident.FieldStatus, field.TypeString, value) + _node.Status = value + } + if value, ok := _c.mutation.CreatedAt(); ok { + _spec.SetField(incident.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := _c.mutation.ModifiedAt(); ok { + _spec.SetField(incident.FieldModifiedAt, field.TypeTime, value) + _node.ModifiedAt = value + } + if value, ok := _c.mutation.DeletedAt(); ok { + _spec.SetField(incident.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = value + } + if value, ok := _c.mutation.CreatedBy(); ok { + _spec.SetField(incident.FieldCreatedBy, field.TypeString, value) + _node.CreatedBy = value + } + if value, ok := _c.mutation.ContactEmail(); ok { + _spec.SetField(incident.FieldContactEmail, field.TypeString, value) + _node.ContactEmail = value + } + if value, ok := _c.mutation.Version(); ok { + _spec.SetField(incident.FieldVersion, field.TypeInt, value) + _node.Version = value + } + if nodes := _c.mutation.ComponentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: incident.ComponentsTable, + Columns: incident.ComponentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := _c.mutation.NotificationsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: incident.NotificationsTable, + Columns: []string{incident.NotificationsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.Incident.Create(). +// SetText(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.IncidentUpsert) { +// SetText(v+v). +// }). +// Exec(ctx) +func (_c *IncidentCreate) OnConflict(opts ...sql.ConflictOption) *IncidentUpsertOne { + _c.conflict = opts + return &IncidentUpsertOne{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.Incident.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *IncidentCreate) OnConflictColumns(columns ...string) *IncidentUpsertOne { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &IncidentUpsertOne{ + create: _c, + } +} + +type ( + // IncidentUpsertOne is the builder for "upsert"-ing + // one Incident node. + IncidentUpsertOne struct { + create *IncidentCreate + } + + // IncidentUpsert is the "OnConflict" setter. + IncidentUpsert struct { + *sql.UpdateSet + } +) + +// SetText sets the "text" field. +func (u *IncidentUpsert) SetText(v string) *IncidentUpsert { + u.Set(incident.FieldText, v) + return u +} + +// UpdateText sets the "text" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateText() *IncidentUpsert { + u.SetExcluded(incident.FieldText) + return u +} + +// SetDescription sets the "description" field. +func (u *IncidentUpsert) SetDescription(v string) *IncidentUpsert { + u.Set(incident.FieldDescription, v) + return u +} + +// UpdateDescription sets the "description" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateDescription() *IncidentUpsert { + u.SetExcluded(incident.FieldDescription) + return u +} + +// ClearDescription clears the value of the "description" field. +func (u *IncidentUpsert) ClearDescription() *IncidentUpsert { + u.SetNull(incident.FieldDescription) + return u +} + +// SetStartDate sets the "start_date" field. +func (u *IncidentUpsert) SetStartDate(v time.Time) *IncidentUpsert { + u.Set(incident.FieldStartDate, v) + return u +} + +// UpdateStartDate sets the "start_date" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateStartDate() *IncidentUpsert { + u.SetExcluded(incident.FieldStartDate) + return u +} + +// SetEndDate sets the "end_date" field. +func (u *IncidentUpsert) SetEndDate(v time.Time) *IncidentUpsert { + u.Set(incident.FieldEndDate, v) + return u +} + +// UpdateEndDate sets the "end_date" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateEndDate() *IncidentUpsert { + u.SetExcluded(incident.FieldEndDate) + return u +} + +// ClearEndDate clears the value of the "end_date" field. +func (u *IncidentUpsert) ClearEndDate() *IncidentUpsert { + u.SetNull(incident.FieldEndDate) + return u +} + +// SetImpact sets the "impact" field. +func (u *IncidentUpsert) SetImpact(v int) *IncidentUpsert { + u.Set(incident.FieldImpact, v) + return u +} + +// UpdateImpact sets the "impact" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateImpact() *IncidentUpsert { + u.SetExcluded(incident.FieldImpact) + return u +} + +// AddImpact adds v to the "impact" field. +func (u *IncidentUpsert) AddImpact(v int) *IncidentUpsert { + u.Add(incident.FieldImpact, v) + return u +} + +// SetSystem sets the "system" field. +func (u *IncidentUpsert) SetSystem(v bool) *IncidentUpsert { + u.Set(incident.FieldSystem, v) + return u +} + +// UpdateSystem sets the "system" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateSystem() *IncidentUpsert { + u.SetExcluded(incident.FieldSystem) + return u +} + +// SetType sets the "type" field. +func (u *IncidentUpsert) SetType(v incident.Type) *IncidentUpsert { + u.Set(incident.FieldType, v) + return u +} + +// UpdateType sets the "type" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateType() *IncidentUpsert { + u.SetExcluded(incident.FieldType) + return u +} + +// SetStatus sets the "status" field. +func (u *IncidentUpsert) SetStatus(v string) *IncidentUpsert { + u.Set(incident.FieldStatus, v) + return u +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateStatus() *IncidentUpsert { + u.SetExcluded(incident.FieldStatus) + return u +} + +// ClearStatus clears the value of the "status" field. +func (u *IncidentUpsert) ClearStatus() *IncidentUpsert { + u.SetNull(incident.FieldStatus) + return u +} + +// SetCreatedAt sets the "created_at" field. +func (u *IncidentUpsert) SetCreatedAt(v time.Time) *IncidentUpsert { + u.Set(incident.FieldCreatedAt, v) + return u +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateCreatedAt() *IncidentUpsert { + u.SetExcluded(incident.FieldCreatedAt) + return u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *IncidentUpsert) ClearCreatedAt() *IncidentUpsert { + u.SetNull(incident.FieldCreatedAt) + return u +} + +// SetModifiedAt sets the "modified_at" field. +func (u *IncidentUpsert) SetModifiedAt(v time.Time) *IncidentUpsert { + u.Set(incident.FieldModifiedAt, v) + return u +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateModifiedAt() *IncidentUpsert { + u.SetExcluded(incident.FieldModifiedAt) + return u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *IncidentUpsert) ClearModifiedAt() *IncidentUpsert { + u.SetNull(incident.FieldModifiedAt) + return u +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *IncidentUpsert) SetDeletedAt(v time.Time) *IncidentUpsert { + u.Set(incident.FieldDeletedAt, v) + return u +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateDeletedAt() *IncidentUpsert { + u.SetExcluded(incident.FieldDeletedAt) + return u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *IncidentUpsert) ClearDeletedAt() *IncidentUpsert { + u.SetNull(incident.FieldDeletedAt) + return u +} + +// SetCreatedBy sets the "created_by" field. +func (u *IncidentUpsert) SetCreatedBy(v string) *IncidentUpsert { + u.Set(incident.FieldCreatedBy, v) + return u +} + +// UpdateCreatedBy sets the "created_by" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateCreatedBy() *IncidentUpsert { + u.SetExcluded(incident.FieldCreatedBy) + return u +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (u *IncidentUpsert) ClearCreatedBy() *IncidentUpsert { + u.SetNull(incident.FieldCreatedBy) + return u +} + +// SetContactEmail sets the "contact_email" field. +func (u *IncidentUpsert) SetContactEmail(v string) *IncidentUpsert { + u.Set(incident.FieldContactEmail, v) + return u +} + +// UpdateContactEmail sets the "contact_email" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateContactEmail() *IncidentUpsert { + u.SetExcluded(incident.FieldContactEmail) + return u +} + +// ClearContactEmail clears the value of the "contact_email" field. +func (u *IncidentUpsert) ClearContactEmail() *IncidentUpsert { + u.SetNull(incident.FieldContactEmail) + return u +} + +// SetVersion sets the "version" field. +func (u *IncidentUpsert) SetVersion(v int) *IncidentUpsert { + u.Set(incident.FieldVersion, v) + return u +} + +// UpdateVersion sets the "version" field to the value that was provided on create. +func (u *IncidentUpsert) UpdateVersion() *IncidentUpsert { + u.SetExcluded(incident.FieldVersion) + return u +} + +// AddVersion adds v to the "version" field. +func (u *IncidentUpsert) AddVersion(v int) *IncidentUpsert { + u.Add(incident.FieldVersion, v) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. +// Using this option is equivalent to using: +// +// client.Incident.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(incident.FieldID) +// }), +// ). +// Exec(ctx) +func (u *IncidentUpsertOne) UpdateNewValues() *IncidentUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.ID(); exists { + s.SetIgnore(incident.FieldID) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.Incident.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *IncidentUpsertOne) Ignore() *IncidentUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *IncidentUpsertOne) DoNothing() *IncidentUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the IncidentCreate.OnConflict +// documentation for more info. +func (u *IncidentUpsertOne) Update(set func(*IncidentUpsert)) *IncidentUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&IncidentUpsert{UpdateSet: update}) + })) + return u +} + +// SetText sets the "text" field. +func (u *IncidentUpsertOne) SetText(v string) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetText(v) + }) +} + +// UpdateText sets the "text" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateText() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateText() + }) +} + +// SetDescription sets the "description" field. +func (u *IncidentUpsertOne) SetDescription(v string) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetDescription(v) + }) +} + +// UpdateDescription sets the "description" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateDescription() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateDescription() + }) +} + +// ClearDescription clears the value of the "description" field. +func (u *IncidentUpsertOne) ClearDescription() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.ClearDescription() + }) +} + +// SetStartDate sets the "start_date" field. +func (u *IncidentUpsertOne) SetStartDate(v time.Time) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetStartDate(v) + }) +} + +// UpdateStartDate sets the "start_date" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateStartDate() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateStartDate() + }) +} + +// SetEndDate sets the "end_date" field. +func (u *IncidentUpsertOne) SetEndDate(v time.Time) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetEndDate(v) + }) +} + +// UpdateEndDate sets the "end_date" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateEndDate() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateEndDate() + }) +} + +// ClearEndDate clears the value of the "end_date" field. +func (u *IncidentUpsertOne) ClearEndDate() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.ClearEndDate() + }) +} + +// SetImpact sets the "impact" field. +func (u *IncidentUpsertOne) SetImpact(v int) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetImpact(v) + }) +} + +// AddImpact adds v to the "impact" field. +func (u *IncidentUpsertOne) AddImpact(v int) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.AddImpact(v) + }) +} + +// UpdateImpact sets the "impact" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateImpact() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateImpact() + }) +} + +// SetSystem sets the "system" field. +func (u *IncidentUpsertOne) SetSystem(v bool) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetSystem(v) + }) +} + +// UpdateSystem sets the "system" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateSystem() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateSystem() + }) +} + +// SetType sets the "type" field. +func (u *IncidentUpsertOne) SetType(v incident.Type) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetType(v) + }) +} + +// UpdateType sets the "type" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateType() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateType() + }) +} + +// SetStatus sets the "status" field. +func (u *IncidentUpsertOne) SetStatus(v string) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateStatus() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateStatus() + }) +} + +// ClearStatus clears the value of the "status" field. +func (u *IncidentUpsertOne) ClearStatus() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.ClearStatus() + }) +} + +// SetCreatedAt sets the "created_at" field. +func (u *IncidentUpsertOne) SetCreatedAt(v time.Time) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateCreatedAt() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateCreatedAt() + }) +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *IncidentUpsertOne) ClearCreatedAt() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.ClearCreatedAt() + }) +} + +// SetModifiedAt sets the "modified_at" field. +func (u *IncidentUpsertOne) SetModifiedAt(v time.Time) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetModifiedAt(v) + }) +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateModifiedAt() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateModifiedAt() + }) +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *IncidentUpsertOne) ClearModifiedAt() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.ClearModifiedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *IncidentUpsertOne) SetDeletedAt(v time.Time) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateDeletedAt() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *IncidentUpsertOne) ClearDeletedAt() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.ClearDeletedAt() + }) +} + +// SetCreatedBy sets the "created_by" field. +func (u *IncidentUpsertOne) SetCreatedBy(v string) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetCreatedBy(v) + }) +} + +// UpdateCreatedBy sets the "created_by" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateCreatedBy() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateCreatedBy() + }) +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (u *IncidentUpsertOne) ClearCreatedBy() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.ClearCreatedBy() + }) +} + +// SetContactEmail sets the "contact_email" field. +func (u *IncidentUpsertOne) SetContactEmail(v string) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetContactEmail(v) + }) +} + +// UpdateContactEmail sets the "contact_email" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateContactEmail() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateContactEmail() + }) +} + +// ClearContactEmail clears the value of the "contact_email" field. +func (u *IncidentUpsertOne) ClearContactEmail() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.ClearContactEmail() + }) +} + +// SetVersion sets the "version" field. +func (u *IncidentUpsertOne) SetVersion(v int) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.SetVersion(v) + }) +} + +// AddVersion adds v to the "version" field. +func (u *IncidentUpsertOne) AddVersion(v int) *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.AddVersion(v) + }) +} + +// UpdateVersion sets the "version" field to the value that was provided on create. +func (u *IncidentUpsertOne) UpdateVersion() *IncidentUpsertOne { + return u.Update(func(s *IncidentUpsert) { + s.UpdateVersion() + }) +} + +// Exec executes the query. +func (u *IncidentUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for IncidentCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *IncidentUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *IncidentUpsertOne) ID(ctx context.Context) (id int, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *IncidentUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// IncidentCreateBulk is the builder for creating many Incident entities in bulk. +type IncidentCreateBulk struct { + config + err error + builders []*IncidentCreate + conflict []sql.ConflictOption +} + +// Save creates the Incident entities in the database. +func (_c *IncidentCreateBulk) Save(ctx context.Context) ([]*Incident, error) { + if _c.err != nil { + return nil, _c.err + } + specs := make([]*sqlgraph.CreateSpec, len(_c.builders)) + nodes := make([]*Incident, len(_c.builders)) + mutators := make([]Mutator, len(_c.builders)) + for i := range _c.builders { + func(i int, root context.Context) { + builder := _c.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*IncidentMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = _c.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (_c *IncidentCreateBulk) SaveX(ctx context.Context) []*Incident { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *IncidentCreateBulk) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *IncidentCreateBulk) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.Incident.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.IncidentUpsert) { +// SetText(v+v). +// }). +// Exec(ctx) +func (_c *IncidentCreateBulk) OnConflict(opts ...sql.ConflictOption) *IncidentUpsertBulk { + _c.conflict = opts + return &IncidentUpsertBulk{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.Incident.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *IncidentCreateBulk) OnConflictColumns(columns ...string) *IncidentUpsertBulk { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &IncidentUpsertBulk{ + create: _c, + } +} + +// IncidentUpsertBulk is the builder for "upsert"-ing +// a bulk of Incident nodes. +type IncidentUpsertBulk struct { + create *IncidentCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.Incident.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(incident.FieldID) +// }), +// ). +// Exec(ctx) +func (u *IncidentUpsertBulk) UpdateNewValues() *IncidentUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.ID(); exists { + s.SetIgnore(incident.FieldID) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.Incident.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *IncidentUpsertBulk) Ignore() *IncidentUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *IncidentUpsertBulk) DoNothing() *IncidentUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the IncidentCreateBulk.OnConflict +// documentation for more info. +func (u *IncidentUpsertBulk) Update(set func(*IncidentUpsert)) *IncidentUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&IncidentUpsert{UpdateSet: update}) + })) + return u +} + +// SetText sets the "text" field. +func (u *IncidentUpsertBulk) SetText(v string) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetText(v) + }) +} + +// UpdateText sets the "text" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateText() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateText() + }) +} + +// SetDescription sets the "description" field. +func (u *IncidentUpsertBulk) SetDescription(v string) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetDescription(v) + }) +} + +// UpdateDescription sets the "description" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateDescription() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateDescription() + }) +} + +// ClearDescription clears the value of the "description" field. +func (u *IncidentUpsertBulk) ClearDescription() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.ClearDescription() + }) +} + +// SetStartDate sets the "start_date" field. +func (u *IncidentUpsertBulk) SetStartDate(v time.Time) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetStartDate(v) + }) +} + +// UpdateStartDate sets the "start_date" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateStartDate() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateStartDate() + }) +} + +// SetEndDate sets the "end_date" field. +func (u *IncidentUpsertBulk) SetEndDate(v time.Time) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetEndDate(v) + }) +} + +// UpdateEndDate sets the "end_date" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateEndDate() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateEndDate() + }) +} + +// ClearEndDate clears the value of the "end_date" field. +func (u *IncidentUpsertBulk) ClearEndDate() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.ClearEndDate() + }) +} + +// SetImpact sets the "impact" field. +func (u *IncidentUpsertBulk) SetImpact(v int) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetImpact(v) + }) +} + +// AddImpact adds v to the "impact" field. +func (u *IncidentUpsertBulk) AddImpact(v int) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.AddImpact(v) + }) +} + +// UpdateImpact sets the "impact" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateImpact() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateImpact() + }) +} + +// SetSystem sets the "system" field. +func (u *IncidentUpsertBulk) SetSystem(v bool) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetSystem(v) + }) +} + +// UpdateSystem sets the "system" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateSystem() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateSystem() + }) +} + +// SetType sets the "type" field. +func (u *IncidentUpsertBulk) SetType(v incident.Type) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetType(v) + }) +} + +// UpdateType sets the "type" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateType() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateType() + }) +} + +// SetStatus sets the "status" field. +func (u *IncidentUpsertBulk) SetStatus(v string) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateStatus() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateStatus() + }) +} + +// ClearStatus clears the value of the "status" field. +func (u *IncidentUpsertBulk) ClearStatus() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.ClearStatus() + }) +} + +// SetCreatedAt sets the "created_at" field. +func (u *IncidentUpsertBulk) SetCreatedAt(v time.Time) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateCreatedAt() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateCreatedAt() + }) +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *IncidentUpsertBulk) ClearCreatedAt() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.ClearCreatedAt() + }) +} + +// SetModifiedAt sets the "modified_at" field. +func (u *IncidentUpsertBulk) SetModifiedAt(v time.Time) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetModifiedAt(v) + }) +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateModifiedAt() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateModifiedAt() + }) +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *IncidentUpsertBulk) ClearModifiedAt() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.ClearModifiedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *IncidentUpsertBulk) SetDeletedAt(v time.Time) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateDeletedAt() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *IncidentUpsertBulk) ClearDeletedAt() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.ClearDeletedAt() + }) +} + +// SetCreatedBy sets the "created_by" field. +func (u *IncidentUpsertBulk) SetCreatedBy(v string) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetCreatedBy(v) + }) +} + +// UpdateCreatedBy sets the "created_by" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateCreatedBy() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateCreatedBy() + }) +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (u *IncidentUpsertBulk) ClearCreatedBy() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.ClearCreatedBy() + }) +} + +// SetContactEmail sets the "contact_email" field. +func (u *IncidentUpsertBulk) SetContactEmail(v string) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetContactEmail(v) + }) +} + +// UpdateContactEmail sets the "contact_email" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateContactEmail() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateContactEmail() + }) +} + +// ClearContactEmail clears the value of the "contact_email" field. +func (u *IncidentUpsertBulk) ClearContactEmail() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.ClearContactEmail() + }) +} + +// SetVersion sets the "version" field. +func (u *IncidentUpsertBulk) SetVersion(v int) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.SetVersion(v) + }) +} + +// AddVersion adds v to the "version" field. +func (u *IncidentUpsertBulk) AddVersion(v int) *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.AddVersion(v) + }) +} + +// UpdateVersion sets the "version" field to the value that was provided on create. +func (u *IncidentUpsertBulk) UpdateVersion() *IncidentUpsertBulk { + return u.Update(func(s *IncidentUpsert) { + s.UpdateVersion() + }) +} + +// Exec executes the query. +func (u *IncidentUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the IncidentCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for IncidentCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *IncidentUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/incident_delete.go b/ent/incident_delete.go new file mode 100644 index 0000000..413d6ce --- /dev/null +++ b/ent/incident_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// IncidentDelete is the builder for deleting a Incident entity. +type IncidentDelete struct { + config + hooks []Hook + mutation *IncidentMutation +} + +// Where appends a list predicates to the IncidentDelete builder. +func (_d *IncidentDelete) Where(ps ...predicate.Incident) *IncidentDelete { + _d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (_d *IncidentDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *IncidentDelete) ExecX(ctx context.Context) int { + n, err := _d.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (_d *IncidentDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(incident.Table, sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt)) + if ps := _d.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + _d.mutation.done = true + return affected, err +} + +// IncidentDeleteOne is the builder for deleting a single Incident entity. +type IncidentDeleteOne struct { + _d *IncidentDelete +} + +// Where appends a list predicates to the IncidentDelete builder. +func (_d *IncidentDeleteOne) Where(ps ...predicate.Incident) *IncidentDeleteOne { + _d._d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query. +func (_d *IncidentDeleteOne) Exec(ctx context.Context) error { + n, err := _d._d.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{incident.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *IncidentDeleteOne) ExecX(ctx context.Context) { + if err := _d.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/incident_query.go b/ent/incident_query.go new file mode 100644 index 0000000..1bb4b6c --- /dev/null +++ b/ent/incident_query.go @@ -0,0 +1,711 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// IncidentQuery is the builder for querying Incident entities. +type IncidentQuery struct { + config + ctx *QueryContext + order []incident.OrderOption + inters []Interceptor + predicates []predicate.Incident + withComponents *ComponentQuery + withNotifications *NotificationOutboxQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the IncidentQuery builder. +func (_q *IncidentQuery) Where(ps ...predicate.Incident) *IncidentQuery { + _q.predicates = append(_q.predicates, ps...) + return _q +} + +// Limit the number of records to be returned by this query. +func (_q *IncidentQuery) Limit(limit int) *IncidentQuery { + _q.ctx.Limit = &limit + return _q +} + +// Offset to start from. +func (_q *IncidentQuery) Offset(offset int) *IncidentQuery { + _q.ctx.Offset = &offset + return _q +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (_q *IncidentQuery) Unique(unique bool) *IncidentQuery { + _q.ctx.Unique = &unique + return _q +} + +// Order specifies how the records should be ordered. +func (_q *IncidentQuery) Order(o ...incident.OrderOption) *IncidentQuery { + _q.order = append(_q.order, o...) + return _q +} + +// QueryComponents chains the current query on the "components" edge. +func (_q *IncidentQuery) QueryComponents() *ComponentQuery { + query := (&ComponentClient{config: _q.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + selector := _q.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(incident.Table, incident.FieldID, selector), + sqlgraph.To(component.Table, component.FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, incident.ComponentsTable, incident.ComponentsPrimaryKey...), + ) + fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryNotifications chains the current query on the "notifications" edge. +func (_q *IncidentQuery) QueryNotifications() *NotificationOutboxQuery { + query := (&NotificationOutboxClient{config: _q.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + selector := _q.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(incident.Table, incident.FieldID, selector), + sqlgraph.To(notificationoutbox.Table, notificationoutbox.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, incident.NotificationsTable, incident.NotificationsColumn), + ) + fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first Incident entity from the query. +// Returns a *NotFoundError when no Incident was found. +func (_q *IncidentQuery) First(ctx context.Context) (*Incident, error) { + nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{incident.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (_q *IncidentQuery) FirstX(ctx context.Context) *Incident { + node, err := _q.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Incident ID from the query. +// Returns a *NotFoundError when no Incident ID was found. +func (_q *IncidentQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{incident.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (_q *IncidentQuery) FirstIDX(ctx context.Context) int { + id, err := _q.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Incident entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one Incident entity is found. +// Returns a *NotFoundError when no Incident entities are found. +func (_q *IncidentQuery) Only(ctx context.Context) (*Incident, error) { + nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{incident.Label} + default: + return nil, &NotSingularError{incident.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (_q *IncidentQuery) OnlyX(ctx context.Context) *Incident { + node, err := _q.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Incident ID in the query. +// Returns a *NotSingularError when more than one Incident ID is found. +// Returns a *NotFoundError when no entities are found. +func (_q *IncidentQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{incident.Label} + default: + err = &NotSingularError{incident.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (_q *IncidentQuery) OnlyIDX(ctx context.Context) int { + id, err := _q.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Incidents. +func (_q *IncidentQuery) All(ctx context.Context) ([]*Incident, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll) + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*Incident, *IncidentQuery]() + return withInterceptors[[]*Incident](ctx, _q, qr, _q.inters) +} + +// AllX is like All, but panics if an error occurs. +func (_q *IncidentQuery) AllX(ctx context.Context) []*Incident { + nodes, err := _q.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Incident IDs. +func (_q *IncidentQuery) IDs(ctx context.Context) (ids []int, err error) { + if _q.ctx.Unique == nil && _q.path != nil { + _q.Unique(true) + } + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs) + if err = _q.Select(incident.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (_q *IncidentQuery) IDsX(ctx context.Context) []int { + ids, err := _q.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (_q *IncidentQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount) + if err := _q.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, _q, querierCount[*IncidentQuery](), _q.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (_q *IncidentQuery) CountX(ctx context.Context) int { + count, err := _q.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (_q *IncidentQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist) + switch _, err := _q.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (_q *IncidentQuery) ExistX(ctx context.Context) bool { + exist, err := _q.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the IncidentQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (_q *IncidentQuery) Clone() *IncidentQuery { + if _q == nil { + return nil + } + return &IncidentQuery{ + config: _q.config, + ctx: _q.ctx.Clone(), + order: append([]incident.OrderOption{}, _q.order...), + inters: append([]Interceptor{}, _q.inters...), + predicates: append([]predicate.Incident{}, _q.predicates...), + withComponents: _q.withComponents.Clone(), + withNotifications: _q.withNotifications.Clone(), + // clone intermediate query. + sql: _q.sql.Clone(), + path: _q.path, + } +} + +// WithComponents tells the query-builder to eager-load the nodes that are connected to +// the "components" edge. The optional arguments are used to configure the query builder of the edge. +func (_q *IncidentQuery) WithComponents(opts ...func(*ComponentQuery)) *IncidentQuery { + query := (&ComponentClient{config: _q.config}).Query() + for _, opt := range opts { + opt(query) + } + _q.withComponents = query + return _q +} + +// WithNotifications tells the query-builder to eager-load the nodes that are connected to +// the "notifications" edge. The optional arguments are used to configure the query builder of the edge. +func (_q *IncidentQuery) WithNotifications(opts ...func(*NotificationOutboxQuery)) *IncidentQuery { + query := (&NotificationOutboxClient{config: _q.config}).Query() + for _, opt := range opts { + opt(query) + } + _q.withNotifications = query + return _q +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Text string `json:"text,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Incident.Query(). +// GroupBy(incident.FieldText). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (_q *IncidentQuery) GroupBy(field string, fields ...string) *IncidentGroupBy { + _q.ctx.Fields = append([]string{field}, fields...) + grbuild := &IncidentGroupBy{build: _q} + grbuild.flds = &_q.ctx.Fields + grbuild.label = incident.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Text string `json:"text,omitempty"` +// } +// +// client.Incident.Query(). +// Select(incident.FieldText). +// Scan(ctx, &v) +func (_q *IncidentQuery) Select(fields ...string) *IncidentSelect { + _q.ctx.Fields = append(_q.ctx.Fields, fields...) + sbuild := &IncidentSelect{IncidentQuery: _q} + sbuild.label = incident.Label + sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a IncidentSelect configured with the given aggregations. +func (_q *IncidentQuery) Aggregate(fns ...AggregateFunc) *IncidentSelect { + return _q.Select().Aggregate(fns...) +} + +func (_q *IncidentQuery) prepareQuery(ctx context.Context) error { + for _, inter := range _q.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, _q); err != nil { + return err + } + } + } + for _, f := range _q.ctx.Fields { + if !incident.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if _q.path != nil { + prev, err := _q.path(ctx) + if err != nil { + return err + } + _q.sql = prev + } + return nil +} + +func (_q *IncidentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Incident, error) { + var ( + nodes = []*Incident{} + _spec = _q.querySpec() + loadedTypes = [2]bool{ + _q.withComponents != nil, + _q.withNotifications != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*Incident).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &Incident{config: _q.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := _q.withComponents; query != nil { + if err := _q.loadComponents(ctx, query, nodes, + func(n *Incident) { n.Edges.Components = []*Component{} }, + func(n *Incident, e *Component) { n.Edges.Components = append(n.Edges.Components, e) }); err != nil { + return nil, err + } + } + if query := _q.withNotifications; query != nil { + if err := _q.loadNotifications(ctx, query, nodes, + func(n *Incident) { n.Edges.Notifications = []*NotificationOutbox{} }, + func(n *Incident, e *NotificationOutbox) { n.Edges.Notifications = append(n.Edges.Notifications, e) }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (_q *IncidentQuery) loadComponents(ctx context.Context, query *ComponentQuery, nodes []*Incident, init func(*Incident), assign func(*Incident, *Component)) error { + edgeIDs := make([]driver.Value, len(nodes)) + byID := make(map[int]*Incident) + nids := make(map[int]map[*Incident]struct{}) + for i, node := range nodes { + edgeIDs[i] = node.ID + byID[node.ID] = node + if init != nil { + init(node) + } + } + query.Where(func(s *sql.Selector) { + joinT := sql.Table(incident.ComponentsTable) + s.Join(joinT).On(s.C(component.FieldID), joinT.C(incident.ComponentsPrimaryKey[1])) + s.Where(sql.InValues(joinT.C(incident.ComponentsPrimaryKey[0]), edgeIDs...)) + columns := s.SelectedColumns() + s.Select(joinT.C(incident.ComponentsPrimaryKey[0])) + s.AppendSelect(columns...) + s.SetDistinct(false) + }) + if err := query.prepareQuery(ctx); err != nil { + return err + } + qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) { + return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) { + assign := spec.Assign + values := spec.ScanValues + spec.ScanValues = func(columns []string) ([]any, error) { + values, err := values(columns[1:]) + if err != nil { + return nil, err + } + return append([]any{new(sql.NullInt64)}, values...), nil + } + spec.Assign = func(columns []string, values []any) error { + outValue := int(values[0].(*sql.NullInt64).Int64) + inValue := int(values[1].(*sql.NullInt64).Int64) + if nids[inValue] == nil { + nids[inValue] = map[*Incident]struct{}{byID[outValue]: {}} + return assign(columns[1:], values[1:]) + } + nids[inValue][byID[outValue]] = struct{}{} + return nil + } + }) + }) + neighbors, err := withInterceptors[[]*Component](ctx, query, qr, query.inters) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nids[n.ID] + if !ok { + return fmt.Errorf(`unexpected "components" node returned %v`, n.ID) + } + for kn := range nodes { + assign(kn, n) + } + } + return nil +} +func (_q *IncidentQuery) loadNotifications(ctx context.Context, query *NotificationOutboxQuery, nodes []*Incident, init func(*Incident), assign func(*Incident, *NotificationOutbox)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*Incident) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(notificationoutbox.FieldIncidentID) + } + query.Where(predicate.NotificationOutbox(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(incident.NotificationsColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.IncidentID + node, ok := nodeids[fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "incident_id" returned %v for node %v`, fk, n.ID) + } + assign(node, n) + } + return nil +} + +func (_q *IncidentQuery) sqlCount(ctx context.Context) (int, error) { + _spec := _q.querySpec() + _spec.Node.Columns = _q.ctx.Fields + if len(_q.ctx.Fields) > 0 { + _spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique + } + return sqlgraph.CountNodes(ctx, _q.driver, _spec) +} + +func (_q *IncidentQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(incident.Table, incident.Columns, sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt)) + _spec.From = _q.sql + if unique := _q.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if _q.path != nil { + _spec.Unique = true + } + if fields := _q.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, incident.FieldID) + for i := range fields { + if fields[i] != incident.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := _q.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := _q.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := _q.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := _q.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (_q *IncidentQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(_q.driver.Dialect()) + t1 := builder.Table(incident.Table) + columns := _q.ctx.Fields + if len(columns) == 0 { + columns = incident.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if _q.sql != nil { + selector = _q.sql + selector.Select(selector.Columns(columns...)...) + } + if _q.ctx.Unique != nil && *_q.ctx.Unique { + selector.Distinct() + } + for _, p := range _q.predicates { + p(selector) + } + for _, p := range _q.order { + p(selector) + } + if offset := _q.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := _q.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// IncidentGroupBy is the group-by builder for Incident entities. +type IncidentGroupBy struct { + selector + build *IncidentQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (_g *IncidentGroupBy) Aggregate(fns ...AggregateFunc) *IncidentGroupBy { + _g.fns = append(_g.fns, fns...) + return _g +} + +// Scan applies the selector query and scans the result into the given value. +func (_g *IncidentGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy) + if err := _g.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*IncidentQuery, *IncidentGroupBy](ctx, _g.build, _g, _g.build.inters, v) +} + +func (_g *IncidentGroupBy) sqlScan(ctx context.Context, root *IncidentQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(_g.fns)) + for _, fn := range _g.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*_g.flds)+len(_g.fns)) + for _, f := range *_g.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*_g.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _g.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// IncidentSelect is the builder for selecting fields of Incident entities. +type IncidentSelect struct { + *IncidentQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (_s *IncidentSelect) Aggregate(fns ...AggregateFunc) *IncidentSelect { + _s.fns = append(_s.fns, fns...) + return _s +} + +// Scan applies the selector query and scans the result into the given value. +func (_s *IncidentSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect) + if err := _s.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*IncidentQuery, *IncidentSelect](ctx, _s.IncidentQuery, _s, _s.inters, v) +} + +func (_s *IncidentSelect) sqlScan(ctx context.Context, root *IncidentQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(_s.fns)) + for _, fn := range _s.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*_s.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _s.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/incident_update.go b/ent/incident_update.go new file mode 100644 index 0000000..f4ebaaf --- /dev/null +++ b/ent/incident_update.go @@ -0,0 +1,1198 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// IncidentUpdate is the builder for updating Incident entities. +type IncidentUpdate struct { + config + hooks []Hook + mutation *IncidentMutation +} + +// Where appends a list predicates to the IncidentUpdate builder. +func (_u *IncidentUpdate) Where(ps ...predicate.Incident) *IncidentUpdate { + _u.mutation.Where(ps...) + return _u +} + +// SetText sets the "text" field. +func (_u *IncidentUpdate) SetText(v string) *IncidentUpdate { + _u.mutation.SetText(v) + return _u +} + +// SetNillableText sets the "text" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableText(v *string) *IncidentUpdate { + if v != nil { + _u.SetText(*v) + } + return _u +} + +// SetDescription sets the "description" field. +func (_u *IncidentUpdate) SetDescription(v string) *IncidentUpdate { + _u.mutation.SetDescription(v) + return _u +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableDescription(v *string) *IncidentUpdate { + if v != nil { + _u.SetDescription(*v) + } + return _u +} + +// ClearDescription clears the value of the "description" field. +func (_u *IncidentUpdate) ClearDescription() *IncidentUpdate { + _u.mutation.ClearDescription() + return _u +} + +// SetStartDate sets the "start_date" field. +func (_u *IncidentUpdate) SetStartDate(v time.Time) *IncidentUpdate { + _u.mutation.SetStartDate(v) + return _u +} + +// SetNillableStartDate sets the "start_date" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableStartDate(v *time.Time) *IncidentUpdate { + if v != nil { + _u.SetStartDate(*v) + } + return _u +} + +// SetEndDate sets the "end_date" field. +func (_u *IncidentUpdate) SetEndDate(v time.Time) *IncidentUpdate { + _u.mutation.SetEndDate(v) + return _u +} + +// SetNillableEndDate sets the "end_date" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableEndDate(v *time.Time) *IncidentUpdate { + if v != nil { + _u.SetEndDate(*v) + } + return _u +} + +// ClearEndDate clears the value of the "end_date" field. +func (_u *IncidentUpdate) ClearEndDate() *IncidentUpdate { + _u.mutation.ClearEndDate() + return _u +} + +// SetImpact sets the "impact" field. +func (_u *IncidentUpdate) SetImpact(v int) *IncidentUpdate { + _u.mutation.ResetImpact() + _u.mutation.SetImpact(v) + return _u +} + +// SetNillableImpact sets the "impact" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableImpact(v *int) *IncidentUpdate { + if v != nil { + _u.SetImpact(*v) + } + return _u +} + +// AddImpact adds value to the "impact" field. +func (_u *IncidentUpdate) AddImpact(v int) *IncidentUpdate { + _u.mutation.AddImpact(v) + return _u +} + +// SetSystem sets the "system" field. +func (_u *IncidentUpdate) SetSystem(v bool) *IncidentUpdate { + _u.mutation.SetSystem(v) + return _u +} + +// SetNillableSystem sets the "system" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableSystem(v *bool) *IncidentUpdate { + if v != nil { + _u.SetSystem(*v) + } + return _u +} + +// SetType sets the "type" field. +func (_u *IncidentUpdate) SetType(v incident.Type) *IncidentUpdate { + _u.mutation.SetType(v) + return _u +} + +// SetNillableType sets the "type" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableType(v *incident.Type) *IncidentUpdate { + if v != nil { + _u.SetType(*v) + } + return _u +} + +// SetStatus sets the "status" field. +func (_u *IncidentUpdate) SetStatus(v string) *IncidentUpdate { + _u.mutation.SetStatus(v) + return _u +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableStatus(v *string) *IncidentUpdate { + if v != nil { + _u.SetStatus(*v) + } + return _u +} + +// ClearStatus clears the value of the "status" field. +func (_u *IncidentUpdate) ClearStatus() *IncidentUpdate { + _u.mutation.ClearStatus() + return _u +} + +// SetCreatedAt sets the "created_at" field. +func (_u *IncidentUpdate) SetCreatedAt(v time.Time) *IncidentUpdate { + _u.mutation.SetCreatedAt(v) + return _u +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableCreatedAt(v *time.Time) *IncidentUpdate { + if v != nil { + _u.SetCreatedAt(*v) + } + return _u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (_u *IncidentUpdate) ClearCreatedAt() *IncidentUpdate { + _u.mutation.ClearCreatedAt() + return _u +} + +// SetModifiedAt sets the "modified_at" field. +func (_u *IncidentUpdate) SetModifiedAt(v time.Time) *IncidentUpdate { + _u.mutation.SetModifiedAt(v) + return _u +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableModifiedAt(v *time.Time) *IncidentUpdate { + if v != nil { + _u.SetModifiedAt(*v) + } + return _u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (_u *IncidentUpdate) ClearModifiedAt() *IncidentUpdate { + _u.mutation.ClearModifiedAt() + return _u +} + +// SetDeletedAt sets the "deleted_at" field. +func (_u *IncidentUpdate) SetDeletedAt(v time.Time) *IncidentUpdate { + _u.mutation.SetDeletedAt(v) + return _u +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableDeletedAt(v *time.Time) *IncidentUpdate { + if v != nil { + _u.SetDeletedAt(*v) + } + return _u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (_u *IncidentUpdate) ClearDeletedAt() *IncidentUpdate { + _u.mutation.ClearDeletedAt() + return _u +} + +// SetCreatedBy sets the "created_by" field. +func (_u *IncidentUpdate) SetCreatedBy(v string) *IncidentUpdate { + _u.mutation.SetCreatedBy(v) + return _u +} + +// SetNillableCreatedBy sets the "created_by" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableCreatedBy(v *string) *IncidentUpdate { + if v != nil { + _u.SetCreatedBy(*v) + } + return _u +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (_u *IncidentUpdate) ClearCreatedBy() *IncidentUpdate { + _u.mutation.ClearCreatedBy() + return _u +} + +// SetContactEmail sets the "contact_email" field. +func (_u *IncidentUpdate) SetContactEmail(v string) *IncidentUpdate { + _u.mutation.SetContactEmail(v) + return _u +} + +// SetNillableContactEmail sets the "contact_email" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableContactEmail(v *string) *IncidentUpdate { + if v != nil { + _u.SetContactEmail(*v) + } + return _u +} + +// ClearContactEmail clears the value of the "contact_email" field. +func (_u *IncidentUpdate) ClearContactEmail() *IncidentUpdate { + _u.mutation.ClearContactEmail() + return _u +} + +// SetVersion sets the "version" field. +func (_u *IncidentUpdate) SetVersion(v int) *IncidentUpdate { + _u.mutation.ResetVersion() + _u.mutation.SetVersion(v) + return _u +} + +// SetNillableVersion sets the "version" field if the given value is not nil. +func (_u *IncidentUpdate) SetNillableVersion(v *int) *IncidentUpdate { + if v != nil { + _u.SetVersion(*v) + } + return _u +} + +// AddVersion adds value to the "version" field. +func (_u *IncidentUpdate) AddVersion(v int) *IncidentUpdate { + _u.mutation.AddVersion(v) + return _u +} + +// AddComponentIDs adds the "components" edge to the Component entity by IDs. +func (_u *IncidentUpdate) AddComponentIDs(ids ...int) *IncidentUpdate { + _u.mutation.AddComponentIDs(ids...) + return _u +} + +// AddComponents adds the "components" edges to the Component entity. +func (_u *IncidentUpdate) AddComponents(v ...*Component) *IncidentUpdate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.AddComponentIDs(ids...) +} + +// AddNotificationIDs adds the "notifications" edge to the NotificationOutbox entity by IDs. +func (_u *IncidentUpdate) AddNotificationIDs(ids ...int) *IncidentUpdate { + _u.mutation.AddNotificationIDs(ids...) + return _u +} + +// AddNotifications adds the "notifications" edges to the NotificationOutbox entity. +func (_u *IncidentUpdate) AddNotifications(v ...*NotificationOutbox) *IncidentUpdate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.AddNotificationIDs(ids...) +} + +// Mutation returns the IncidentMutation object of the builder. +func (_u *IncidentUpdate) Mutation() *IncidentMutation { + return _u.mutation +} + +// ClearComponents clears all "components" edges to the Component entity. +func (_u *IncidentUpdate) ClearComponents() *IncidentUpdate { + _u.mutation.ClearComponents() + return _u +} + +// RemoveComponentIDs removes the "components" edge to Component entities by IDs. +func (_u *IncidentUpdate) RemoveComponentIDs(ids ...int) *IncidentUpdate { + _u.mutation.RemoveComponentIDs(ids...) + return _u +} + +// RemoveComponents removes "components" edges to Component entities. +func (_u *IncidentUpdate) RemoveComponents(v ...*Component) *IncidentUpdate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.RemoveComponentIDs(ids...) +} + +// ClearNotifications clears all "notifications" edges to the NotificationOutbox entity. +func (_u *IncidentUpdate) ClearNotifications() *IncidentUpdate { + _u.mutation.ClearNotifications() + return _u +} + +// RemoveNotificationIDs removes the "notifications" edge to NotificationOutbox entities by IDs. +func (_u *IncidentUpdate) RemoveNotificationIDs(ids ...int) *IncidentUpdate { + _u.mutation.RemoveNotificationIDs(ids...) + return _u +} + +// RemoveNotifications removes "notifications" edges to NotificationOutbox entities. +func (_u *IncidentUpdate) RemoveNotifications(v ...*NotificationOutbox) *IncidentUpdate { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.RemoveNotificationIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (_u *IncidentUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *IncidentUpdate) SaveX(ctx context.Context) int { + affected, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (_u *IncidentUpdate) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *IncidentUpdate) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *IncidentUpdate) check() error { + if v, ok := _u.mutation.Text(); ok { + if err := incident.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Incident.text": %w`, err)} + } + } + if v, ok := _u.mutation.GetType(); ok { + if err := incident.TypeValidator(v); err != nil { + return &ValidationError{Name: "type", err: fmt.Errorf(`ent: validator failed for field "Incident.type": %w`, err)} + } + } + return nil +} + +func (_u *IncidentUpdate) sqlSave(ctx context.Context) (_node int, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(incident.Table, incident.Columns, sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt)) + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.Text(); ok { + _spec.SetField(incident.FieldText, field.TypeString, value) + } + if value, ok := _u.mutation.Description(); ok { + _spec.SetField(incident.FieldDescription, field.TypeString, value) + } + if _u.mutation.DescriptionCleared() { + _spec.ClearField(incident.FieldDescription, field.TypeString) + } + if value, ok := _u.mutation.StartDate(); ok { + _spec.SetField(incident.FieldStartDate, field.TypeTime, value) + } + if value, ok := _u.mutation.EndDate(); ok { + _spec.SetField(incident.FieldEndDate, field.TypeTime, value) + } + if _u.mutation.EndDateCleared() { + _spec.ClearField(incident.FieldEndDate, field.TypeTime) + } + if value, ok := _u.mutation.Impact(); ok { + _spec.SetField(incident.FieldImpact, field.TypeInt, value) + } + if value, ok := _u.mutation.AddedImpact(); ok { + _spec.AddField(incident.FieldImpact, field.TypeInt, value) + } + if value, ok := _u.mutation.System(); ok { + _spec.SetField(incident.FieldSystem, field.TypeBool, value) + } + if value, ok := _u.mutation.GetType(); ok { + _spec.SetField(incident.FieldType, field.TypeEnum, value) + } + if value, ok := _u.mutation.Status(); ok { + _spec.SetField(incident.FieldStatus, field.TypeString, value) + } + if _u.mutation.StatusCleared() { + _spec.ClearField(incident.FieldStatus, field.TypeString) + } + if value, ok := _u.mutation.CreatedAt(); ok { + _spec.SetField(incident.FieldCreatedAt, field.TypeTime, value) + } + if _u.mutation.CreatedAtCleared() { + _spec.ClearField(incident.FieldCreatedAt, field.TypeTime) + } + if value, ok := _u.mutation.ModifiedAt(); ok { + _spec.SetField(incident.FieldModifiedAt, field.TypeTime, value) + } + if _u.mutation.ModifiedAtCleared() { + _spec.ClearField(incident.FieldModifiedAt, field.TypeTime) + } + if value, ok := _u.mutation.DeletedAt(); ok { + _spec.SetField(incident.FieldDeletedAt, field.TypeTime, value) + } + if _u.mutation.DeletedAtCleared() { + _spec.ClearField(incident.FieldDeletedAt, field.TypeTime) + } + if value, ok := _u.mutation.CreatedBy(); ok { + _spec.SetField(incident.FieldCreatedBy, field.TypeString, value) + } + if _u.mutation.CreatedByCleared() { + _spec.ClearField(incident.FieldCreatedBy, field.TypeString) + } + if value, ok := _u.mutation.ContactEmail(); ok { + _spec.SetField(incident.FieldContactEmail, field.TypeString, value) + } + if _u.mutation.ContactEmailCleared() { + _spec.ClearField(incident.FieldContactEmail, field.TypeString) + } + if value, ok := _u.mutation.Version(); ok { + _spec.SetField(incident.FieldVersion, field.TypeInt, value) + } + if value, ok := _u.mutation.AddedVersion(); ok { + _spec.AddField(incident.FieldVersion, field.TypeInt, value) + } + if _u.mutation.ComponentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: incident.ComponentsTable, + Columns: incident.ComponentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.RemovedComponentsIDs(); len(nodes) > 0 && !_u.mutation.ComponentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: incident.ComponentsTable, + Columns: incident.ComponentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.ComponentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: incident.ComponentsTable, + Columns: incident.ComponentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _u.mutation.NotificationsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: incident.NotificationsTable, + Columns: []string{incident.NotificationsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.RemovedNotificationsIDs(); len(nodes) > 0 && !_u.mutation.NotificationsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: incident.NotificationsTable, + Columns: []string{incident.NotificationsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.NotificationsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: incident.NotificationsTable, + Columns: []string{incident.NotificationsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{incident.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + _u.mutation.done = true + return _node, nil +} + +// IncidentUpdateOne is the builder for updating a single Incident entity. +type IncidentUpdateOne struct { + config + fields []string + hooks []Hook + mutation *IncidentMutation +} + +// SetText sets the "text" field. +func (_u *IncidentUpdateOne) SetText(v string) *IncidentUpdateOne { + _u.mutation.SetText(v) + return _u +} + +// SetNillableText sets the "text" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableText(v *string) *IncidentUpdateOne { + if v != nil { + _u.SetText(*v) + } + return _u +} + +// SetDescription sets the "description" field. +func (_u *IncidentUpdateOne) SetDescription(v string) *IncidentUpdateOne { + _u.mutation.SetDescription(v) + return _u +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableDescription(v *string) *IncidentUpdateOne { + if v != nil { + _u.SetDescription(*v) + } + return _u +} + +// ClearDescription clears the value of the "description" field. +func (_u *IncidentUpdateOne) ClearDescription() *IncidentUpdateOne { + _u.mutation.ClearDescription() + return _u +} + +// SetStartDate sets the "start_date" field. +func (_u *IncidentUpdateOne) SetStartDate(v time.Time) *IncidentUpdateOne { + _u.mutation.SetStartDate(v) + return _u +} + +// SetNillableStartDate sets the "start_date" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableStartDate(v *time.Time) *IncidentUpdateOne { + if v != nil { + _u.SetStartDate(*v) + } + return _u +} + +// SetEndDate sets the "end_date" field. +func (_u *IncidentUpdateOne) SetEndDate(v time.Time) *IncidentUpdateOne { + _u.mutation.SetEndDate(v) + return _u +} + +// SetNillableEndDate sets the "end_date" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableEndDate(v *time.Time) *IncidentUpdateOne { + if v != nil { + _u.SetEndDate(*v) + } + return _u +} + +// ClearEndDate clears the value of the "end_date" field. +func (_u *IncidentUpdateOne) ClearEndDate() *IncidentUpdateOne { + _u.mutation.ClearEndDate() + return _u +} + +// SetImpact sets the "impact" field. +func (_u *IncidentUpdateOne) SetImpact(v int) *IncidentUpdateOne { + _u.mutation.ResetImpact() + _u.mutation.SetImpact(v) + return _u +} + +// SetNillableImpact sets the "impact" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableImpact(v *int) *IncidentUpdateOne { + if v != nil { + _u.SetImpact(*v) + } + return _u +} + +// AddImpact adds value to the "impact" field. +func (_u *IncidentUpdateOne) AddImpact(v int) *IncidentUpdateOne { + _u.mutation.AddImpact(v) + return _u +} + +// SetSystem sets the "system" field. +func (_u *IncidentUpdateOne) SetSystem(v bool) *IncidentUpdateOne { + _u.mutation.SetSystem(v) + return _u +} + +// SetNillableSystem sets the "system" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableSystem(v *bool) *IncidentUpdateOne { + if v != nil { + _u.SetSystem(*v) + } + return _u +} + +// SetType sets the "type" field. +func (_u *IncidentUpdateOne) SetType(v incident.Type) *IncidentUpdateOne { + _u.mutation.SetType(v) + return _u +} + +// SetNillableType sets the "type" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableType(v *incident.Type) *IncidentUpdateOne { + if v != nil { + _u.SetType(*v) + } + return _u +} + +// SetStatus sets the "status" field. +func (_u *IncidentUpdateOne) SetStatus(v string) *IncidentUpdateOne { + _u.mutation.SetStatus(v) + return _u +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableStatus(v *string) *IncidentUpdateOne { + if v != nil { + _u.SetStatus(*v) + } + return _u +} + +// ClearStatus clears the value of the "status" field. +func (_u *IncidentUpdateOne) ClearStatus() *IncidentUpdateOne { + _u.mutation.ClearStatus() + return _u +} + +// SetCreatedAt sets the "created_at" field. +func (_u *IncidentUpdateOne) SetCreatedAt(v time.Time) *IncidentUpdateOne { + _u.mutation.SetCreatedAt(v) + return _u +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableCreatedAt(v *time.Time) *IncidentUpdateOne { + if v != nil { + _u.SetCreatedAt(*v) + } + return _u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (_u *IncidentUpdateOne) ClearCreatedAt() *IncidentUpdateOne { + _u.mutation.ClearCreatedAt() + return _u +} + +// SetModifiedAt sets the "modified_at" field. +func (_u *IncidentUpdateOne) SetModifiedAt(v time.Time) *IncidentUpdateOne { + _u.mutation.SetModifiedAt(v) + return _u +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableModifiedAt(v *time.Time) *IncidentUpdateOne { + if v != nil { + _u.SetModifiedAt(*v) + } + return _u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (_u *IncidentUpdateOne) ClearModifiedAt() *IncidentUpdateOne { + _u.mutation.ClearModifiedAt() + return _u +} + +// SetDeletedAt sets the "deleted_at" field. +func (_u *IncidentUpdateOne) SetDeletedAt(v time.Time) *IncidentUpdateOne { + _u.mutation.SetDeletedAt(v) + return _u +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableDeletedAt(v *time.Time) *IncidentUpdateOne { + if v != nil { + _u.SetDeletedAt(*v) + } + return _u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (_u *IncidentUpdateOne) ClearDeletedAt() *IncidentUpdateOne { + _u.mutation.ClearDeletedAt() + return _u +} + +// SetCreatedBy sets the "created_by" field. +func (_u *IncidentUpdateOne) SetCreatedBy(v string) *IncidentUpdateOne { + _u.mutation.SetCreatedBy(v) + return _u +} + +// SetNillableCreatedBy sets the "created_by" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableCreatedBy(v *string) *IncidentUpdateOne { + if v != nil { + _u.SetCreatedBy(*v) + } + return _u +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (_u *IncidentUpdateOne) ClearCreatedBy() *IncidentUpdateOne { + _u.mutation.ClearCreatedBy() + return _u +} + +// SetContactEmail sets the "contact_email" field. +func (_u *IncidentUpdateOne) SetContactEmail(v string) *IncidentUpdateOne { + _u.mutation.SetContactEmail(v) + return _u +} + +// SetNillableContactEmail sets the "contact_email" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableContactEmail(v *string) *IncidentUpdateOne { + if v != nil { + _u.SetContactEmail(*v) + } + return _u +} + +// ClearContactEmail clears the value of the "contact_email" field. +func (_u *IncidentUpdateOne) ClearContactEmail() *IncidentUpdateOne { + _u.mutation.ClearContactEmail() + return _u +} + +// SetVersion sets the "version" field. +func (_u *IncidentUpdateOne) SetVersion(v int) *IncidentUpdateOne { + _u.mutation.ResetVersion() + _u.mutation.SetVersion(v) + return _u +} + +// SetNillableVersion sets the "version" field if the given value is not nil. +func (_u *IncidentUpdateOne) SetNillableVersion(v *int) *IncidentUpdateOne { + if v != nil { + _u.SetVersion(*v) + } + return _u +} + +// AddVersion adds value to the "version" field. +func (_u *IncidentUpdateOne) AddVersion(v int) *IncidentUpdateOne { + _u.mutation.AddVersion(v) + return _u +} + +// AddComponentIDs adds the "components" edge to the Component entity by IDs. +func (_u *IncidentUpdateOne) AddComponentIDs(ids ...int) *IncidentUpdateOne { + _u.mutation.AddComponentIDs(ids...) + return _u +} + +// AddComponents adds the "components" edges to the Component entity. +func (_u *IncidentUpdateOne) AddComponents(v ...*Component) *IncidentUpdateOne { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.AddComponentIDs(ids...) +} + +// AddNotificationIDs adds the "notifications" edge to the NotificationOutbox entity by IDs. +func (_u *IncidentUpdateOne) AddNotificationIDs(ids ...int) *IncidentUpdateOne { + _u.mutation.AddNotificationIDs(ids...) + return _u +} + +// AddNotifications adds the "notifications" edges to the NotificationOutbox entity. +func (_u *IncidentUpdateOne) AddNotifications(v ...*NotificationOutbox) *IncidentUpdateOne { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.AddNotificationIDs(ids...) +} + +// Mutation returns the IncidentMutation object of the builder. +func (_u *IncidentUpdateOne) Mutation() *IncidentMutation { + return _u.mutation +} + +// ClearComponents clears all "components" edges to the Component entity. +func (_u *IncidentUpdateOne) ClearComponents() *IncidentUpdateOne { + _u.mutation.ClearComponents() + return _u +} + +// RemoveComponentIDs removes the "components" edge to Component entities by IDs. +func (_u *IncidentUpdateOne) RemoveComponentIDs(ids ...int) *IncidentUpdateOne { + _u.mutation.RemoveComponentIDs(ids...) + return _u +} + +// RemoveComponents removes "components" edges to Component entities. +func (_u *IncidentUpdateOne) RemoveComponents(v ...*Component) *IncidentUpdateOne { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.RemoveComponentIDs(ids...) +} + +// ClearNotifications clears all "notifications" edges to the NotificationOutbox entity. +func (_u *IncidentUpdateOne) ClearNotifications() *IncidentUpdateOne { + _u.mutation.ClearNotifications() + return _u +} + +// RemoveNotificationIDs removes the "notifications" edge to NotificationOutbox entities by IDs. +func (_u *IncidentUpdateOne) RemoveNotificationIDs(ids ...int) *IncidentUpdateOne { + _u.mutation.RemoveNotificationIDs(ids...) + return _u +} + +// RemoveNotifications removes "notifications" edges to NotificationOutbox entities. +func (_u *IncidentUpdateOne) RemoveNotifications(v ...*NotificationOutbox) *IncidentUpdateOne { + ids := make([]int, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return _u.RemoveNotificationIDs(ids...) +} + +// Where appends a list predicates to the IncidentUpdate builder. +func (_u *IncidentUpdateOne) Where(ps ...predicate.Incident) *IncidentUpdateOne { + _u.mutation.Where(ps...) + return _u +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (_u *IncidentUpdateOne) Select(field string, fields ...string) *IncidentUpdateOne { + _u.fields = append([]string{field}, fields...) + return _u +} + +// Save executes the query and returns the updated Incident entity. +func (_u *IncidentUpdateOne) Save(ctx context.Context) (*Incident, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *IncidentUpdateOne) SaveX(ctx context.Context) *Incident { + node, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (_u *IncidentUpdateOne) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *IncidentUpdateOne) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *IncidentUpdateOne) check() error { + if v, ok := _u.mutation.Text(); ok { + if err := incident.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Incident.text": %w`, err)} + } + } + if v, ok := _u.mutation.GetType(); ok { + if err := incident.TypeValidator(v); err != nil { + return &ValidationError{Name: "type", err: fmt.Errorf(`ent: validator failed for field "Incident.type": %w`, err)} + } + } + return nil +} + +func (_u *IncidentUpdateOne) sqlSave(ctx context.Context) (_node *Incident, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(incident.Table, incident.Columns, sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt)) + id, ok := _u.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Incident.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := _u.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, incident.FieldID) + for _, f := range fields { + if !incident.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != incident.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.Text(); ok { + _spec.SetField(incident.FieldText, field.TypeString, value) + } + if value, ok := _u.mutation.Description(); ok { + _spec.SetField(incident.FieldDescription, field.TypeString, value) + } + if _u.mutation.DescriptionCleared() { + _spec.ClearField(incident.FieldDescription, field.TypeString) + } + if value, ok := _u.mutation.StartDate(); ok { + _spec.SetField(incident.FieldStartDate, field.TypeTime, value) + } + if value, ok := _u.mutation.EndDate(); ok { + _spec.SetField(incident.FieldEndDate, field.TypeTime, value) + } + if _u.mutation.EndDateCleared() { + _spec.ClearField(incident.FieldEndDate, field.TypeTime) + } + if value, ok := _u.mutation.Impact(); ok { + _spec.SetField(incident.FieldImpact, field.TypeInt, value) + } + if value, ok := _u.mutation.AddedImpact(); ok { + _spec.AddField(incident.FieldImpact, field.TypeInt, value) + } + if value, ok := _u.mutation.System(); ok { + _spec.SetField(incident.FieldSystem, field.TypeBool, value) + } + if value, ok := _u.mutation.GetType(); ok { + _spec.SetField(incident.FieldType, field.TypeEnum, value) + } + if value, ok := _u.mutation.Status(); ok { + _spec.SetField(incident.FieldStatus, field.TypeString, value) + } + if _u.mutation.StatusCleared() { + _spec.ClearField(incident.FieldStatus, field.TypeString) + } + if value, ok := _u.mutation.CreatedAt(); ok { + _spec.SetField(incident.FieldCreatedAt, field.TypeTime, value) + } + if _u.mutation.CreatedAtCleared() { + _spec.ClearField(incident.FieldCreatedAt, field.TypeTime) + } + if value, ok := _u.mutation.ModifiedAt(); ok { + _spec.SetField(incident.FieldModifiedAt, field.TypeTime, value) + } + if _u.mutation.ModifiedAtCleared() { + _spec.ClearField(incident.FieldModifiedAt, field.TypeTime) + } + if value, ok := _u.mutation.DeletedAt(); ok { + _spec.SetField(incident.FieldDeletedAt, field.TypeTime, value) + } + if _u.mutation.DeletedAtCleared() { + _spec.ClearField(incident.FieldDeletedAt, field.TypeTime) + } + if value, ok := _u.mutation.CreatedBy(); ok { + _spec.SetField(incident.FieldCreatedBy, field.TypeString, value) + } + if _u.mutation.CreatedByCleared() { + _spec.ClearField(incident.FieldCreatedBy, field.TypeString) + } + if value, ok := _u.mutation.ContactEmail(); ok { + _spec.SetField(incident.FieldContactEmail, field.TypeString, value) + } + if _u.mutation.ContactEmailCleared() { + _spec.ClearField(incident.FieldContactEmail, field.TypeString) + } + if value, ok := _u.mutation.Version(); ok { + _spec.SetField(incident.FieldVersion, field.TypeInt, value) + } + if value, ok := _u.mutation.AddedVersion(); ok { + _spec.AddField(incident.FieldVersion, field.TypeInt, value) + } + if _u.mutation.ComponentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: incident.ComponentsTable, + Columns: incident.ComponentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.RemovedComponentsIDs(); len(nodes) > 0 && !_u.mutation.ComponentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: incident.ComponentsTable, + Columns: incident.ComponentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.ComponentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: incident.ComponentsTable, + Columns: incident.ComponentsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(component.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _u.mutation.NotificationsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: incident.NotificationsTable, + Columns: []string{incident.NotificationsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.RemovedNotificationsIDs(); len(nodes) > 0 && !_u.mutation.NotificationsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: incident.NotificationsTable, + Columns: []string{incident.NotificationsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.NotificationsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: incident.NotificationsTable, + Columns: []string{incident.NotificationsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &Incident{config: _u.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{incident.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + _u.mutation.done = true + return _node, nil +} diff --git a/ent/incidentstatus.go b/ent/incidentstatus.go new file mode 100644 index 0000000..b547839 --- /dev/null +++ b/ent/incidentstatus.go @@ -0,0 +1,194 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" +) + +// IncidentStatus is the model entity for the IncidentStatus schema. +type IncidentStatus struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // IncidentID holds the value of the "incident_id" field. + IncidentID int `json:"incident_id,omitempty"` + // Timestamp holds the value of the "timestamp" field. + Timestamp time.Time `json:"timestamp,omitempty"` + // Text holds the value of the "text" field. + Text string `json:"text,omitempty"` + // Status holds the value of the "status" field. + Status string `json:"status,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // ModifiedAt holds the value of the "modified_at" field. + ModifiedAt time.Time `json:"modified_at,omitempty"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt time.Time `json:"deleted_at,omitempty"` + // CreatedBy holds the value of the "created_by" field. + CreatedBy string `json:"created_by,omitempty"` + // ModifiedBy holds the value of the "modified_by" field. + ModifiedBy string `json:"modified_by,omitempty"` + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*IncidentStatus) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case incidentstatus.FieldID, incidentstatus.FieldIncidentID: + values[i] = new(sql.NullInt64) + case incidentstatus.FieldText, incidentstatus.FieldStatus, incidentstatus.FieldCreatedBy, incidentstatus.FieldModifiedBy: + values[i] = new(sql.NullString) + case incidentstatus.FieldTimestamp, incidentstatus.FieldCreatedAt, incidentstatus.FieldModifiedAt, incidentstatus.FieldDeletedAt: + values[i] = new(sql.NullTime) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the IncidentStatus fields. +func (_m *IncidentStatus) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case incidentstatus.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + _m.ID = int(value.Int64) + case incidentstatus.FieldIncidentID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field incident_id", values[i]) + } else if value.Valid { + _m.IncidentID = int(value.Int64) + } + case incidentstatus.FieldTimestamp: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field timestamp", values[i]) + } else if value.Valid { + _m.Timestamp = value.Time + } + case incidentstatus.FieldText: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field text", values[i]) + } else if value.Valid { + _m.Text = value.String + } + case incidentstatus.FieldStatus: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field status", values[i]) + } else if value.Valid { + _m.Status = value.String + } + case incidentstatus.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + _m.CreatedAt = value.Time + } + case incidentstatus.FieldModifiedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field modified_at", values[i]) + } else if value.Valid { + _m.ModifiedAt = value.Time + } + case incidentstatus.FieldDeletedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value.Valid { + _m.DeletedAt = value.Time + } + case incidentstatus.FieldCreatedBy: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field created_by", values[i]) + } else if value.Valid { + _m.CreatedBy = value.String + } + case incidentstatus.FieldModifiedBy: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field modified_by", values[i]) + } else if value.Valid { + _m.ModifiedBy = value.String + } + default: + _m.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the IncidentStatus. +// This includes values selected through modifiers, order, etc. +func (_m *IncidentStatus) Value(name string) (ent.Value, error) { + return _m.selectValues.Get(name) +} + +// Update returns a builder for updating this IncidentStatus. +// Note that you need to call IncidentStatus.Unwrap() before calling this method if this IncidentStatus +// was returned from a transaction, and the transaction was committed or rolled back. +func (_m *IncidentStatus) Update() *IncidentStatusUpdateOne { + return NewIncidentStatusClient(_m.config).UpdateOne(_m) +} + +// Unwrap unwraps the IncidentStatus entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (_m *IncidentStatus) Unwrap() *IncidentStatus { + _tx, ok := _m.config.driver.(*txDriver) + if !ok { + panic("ent: IncidentStatus is not a transactional entity") + } + _m.config.driver = _tx.drv + return _m +} + +// String implements the fmt.Stringer. +func (_m *IncidentStatus) String() string { + var builder strings.Builder + builder.WriteString("IncidentStatus(") + builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID)) + builder.WriteString("incident_id=") + builder.WriteString(fmt.Sprintf("%v", _m.IncidentID)) + builder.WriteString(", ") + builder.WriteString("timestamp=") + builder.WriteString(_m.Timestamp.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("text=") + builder.WriteString(_m.Text) + builder.WriteString(", ") + builder.WriteString("status=") + builder.WriteString(_m.Status) + builder.WriteString(", ") + builder.WriteString("created_at=") + builder.WriteString(_m.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("modified_at=") + builder.WriteString(_m.ModifiedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("deleted_at=") + builder.WriteString(_m.DeletedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("created_by=") + builder.WriteString(_m.CreatedBy) + builder.WriteString(", ") + builder.WriteString("modified_by=") + builder.WriteString(_m.ModifiedBy) + builder.WriteByte(')') + return builder.String() +} + +// IncidentStatusSlice is a parsable slice of IncidentStatus. +type IncidentStatusSlice []*IncidentStatus diff --git a/ent/incidentstatus/incidentstatus.go b/ent/incidentstatus/incidentstatus.go new file mode 100644 index 0000000..747aa27 --- /dev/null +++ b/ent/incidentstatus/incidentstatus.go @@ -0,0 +1,118 @@ +// Code generated by ent, DO NOT EDIT. + +package incidentstatus + +import ( + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the incidentstatus type in the database. + Label = "incident_status" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldIncidentID holds the string denoting the incident_id field in the database. + FieldIncidentID = "incident_id" + // FieldTimestamp holds the string denoting the timestamp field in the database. + FieldTimestamp = "timestamp" + // FieldText holds the string denoting the text field in the database. + FieldText = "text" + // FieldStatus holds the string denoting the status field in the database. + FieldStatus = "status" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldModifiedAt holds the string denoting the modified_at field in the database. + FieldModifiedAt = "modified_at" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // FieldCreatedBy holds the string denoting the created_by field in the database. + FieldCreatedBy = "created_by" + // FieldModifiedBy holds the string denoting the modified_by field in the database. + FieldModifiedBy = "modified_by" + // Table holds the table name of the incidentstatus in the database. + Table = "incident_status" +) + +// Columns holds all SQL columns for incidentstatus fields. +var Columns = []string{ + FieldID, + FieldIncidentID, + FieldTimestamp, + FieldText, + FieldStatus, + FieldCreatedAt, + FieldModifiedAt, + FieldDeletedAt, + FieldCreatedBy, + FieldModifiedBy, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // TextValidator is a validator for the "text" field. It is called by the builders before save. + TextValidator func(string) error + // StatusValidator is a validator for the "status" field. It is called by the builders before save. + StatusValidator func(string) error +) + +// OrderOption defines the ordering options for the IncidentStatus queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByIncidentID orders the results by the incident_id field. +func ByIncidentID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldIncidentID, opts...).ToFunc() +} + +// ByTimestamp orders the results by the timestamp field. +func ByTimestamp(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldTimestamp, opts...).ToFunc() +} + +// ByText orders the results by the text field. +func ByText(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldText, opts...).ToFunc() +} + +// ByStatus orders the results by the status field. +func ByStatus(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldStatus, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByModifiedAt orders the results by the modified_at field. +func ByModifiedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldModifiedAt, opts...).ToFunc() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByCreatedBy orders the results by the created_by field. +func ByCreatedBy(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedBy, opts...).ToFunc() +} + +// ByModifiedBy orders the results by the modified_by field. +func ByModifiedBy(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldModifiedBy, opts...).ToFunc() +} diff --git a/ent/incidentstatus/where.go b/ent/incidentstatus/where.go new file mode 100644 index 0000000..92927d8 --- /dev/null +++ b/ent/incidentstatus/where.go @@ -0,0 +1,635 @@ +// Code generated by ent, DO NOT EDIT. + +package incidentstatus + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldID, id)) +} + +// IncidentID applies equality check predicate on the "incident_id" field. It's identical to IncidentIDEQ. +func IncidentID(v int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldIncidentID, v)) +} + +// Timestamp applies equality check predicate on the "timestamp" field. It's identical to TimestampEQ. +func Timestamp(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldTimestamp, v)) +} + +// Text applies equality check predicate on the "text" field. It's identical to TextEQ. +func Text(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldText, v)) +} + +// Status applies equality check predicate on the "status" field. It's identical to StatusEQ. +func Status(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldStatus, v)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldCreatedAt, v)) +} + +// ModifiedAt applies equality check predicate on the "modified_at" field. It's identical to ModifiedAtEQ. +func ModifiedAt(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldModifiedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldDeletedAt, v)) +} + +// CreatedBy applies equality check predicate on the "created_by" field. It's identical to CreatedByEQ. +func CreatedBy(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldCreatedBy, v)) +} + +// ModifiedBy applies equality check predicate on the "modified_by" field. It's identical to ModifiedByEQ. +func ModifiedBy(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldModifiedBy, v)) +} + +// IncidentIDEQ applies the EQ predicate on the "incident_id" field. +func IncidentIDEQ(v int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldIncidentID, v)) +} + +// IncidentIDNEQ applies the NEQ predicate on the "incident_id" field. +func IncidentIDNEQ(v int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldIncidentID, v)) +} + +// IncidentIDIn applies the In predicate on the "incident_id" field. +func IncidentIDIn(vs ...int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldIncidentID, vs...)) +} + +// IncidentIDNotIn applies the NotIn predicate on the "incident_id" field. +func IncidentIDNotIn(vs ...int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldIncidentID, vs...)) +} + +// IncidentIDGT applies the GT predicate on the "incident_id" field. +func IncidentIDGT(v int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldIncidentID, v)) +} + +// IncidentIDGTE applies the GTE predicate on the "incident_id" field. +func IncidentIDGTE(v int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldIncidentID, v)) +} + +// IncidentIDLT applies the LT predicate on the "incident_id" field. +func IncidentIDLT(v int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldIncidentID, v)) +} + +// IncidentIDLTE applies the LTE predicate on the "incident_id" field. +func IncidentIDLTE(v int) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldIncidentID, v)) +} + +// IncidentIDIsNil applies the IsNil predicate on the "incident_id" field. +func IncidentIDIsNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIsNull(FieldIncidentID)) +} + +// IncidentIDNotNil applies the NotNil predicate on the "incident_id" field. +func IncidentIDNotNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotNull(FieldIncidentID)) +} + +// TimestampEQ applies the EQ predicate on the "timestamp" field. +func TimestampEQ(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldTimestamp, v)) +} + +// TimestampNEQ applies the NEQ predicate on the "timestamp" field. +func TimestampNEQ(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldTimestamp, v)) +} + +// TimestampIn applies the In predicate on the "timestamp" field. +func TimestampIn(vs ...time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldTimestamp, vs...)) +} + +// TimestampNotIn applies the NotIn predicate on the "timestamp" field. +func TimestampNotIn(vs ...time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldTimestamp, vs...)) +} + +// TimestampGT applies the GT predicate on the "timestamp" field. +func TimestampGT(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldTimestamp, v)) +} + +// TimestampGTE applies the GTE predicate on the "timestamp" field. +func TimestampGTE(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldTimestamp, v)) +} + +// TimestampLT applies the LT predicate on the "timestamp" field. +func TimestampLT(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldTimestamp, v)) +} + +// TimestampLTE applies the LTE predicate on the "timestamp" field. +func TimestampLTE(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldTimestamp, v)) +} + +// TextEQ applies the EQ predicate on the "text" field. +func TextEQ(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldText, v)) +} + +// TextNEQ applies the NEQ predicate on the "text" field. +func TextNEQ(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldText, v)) +} + +// TextIn applies the In predicate on the "text" field. +func TextIn(vs ...string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldText, vs...)) +} + +// TextNotIn applies the NotIn predicate on the "text" field. +func TextNotIn(vs ...string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldText, vs...)) +} + +// TextGT applies the GT predicate on the "text" field. +func TextGT(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldText, v)) +} + +// TextGTE applies the GTE predicate on the "text" field. +func TextGTE(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldText, v)) +} + +// TextLT applies the LT predicate on the "text" field. +func TextLT(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldText, v)) +} + +// TextLTE applies the LTE predicate on the "text" field. +func TextLTE(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldText, v)) +} + +// TextContains applies the Contains predicate on the "text" field. +func TextContains(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldContains(FieldText, v)) +} + +// TextHasPrefix applies the HasPrefix predicate on the "text" field. +func TextHasPrefix(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldHasPrefix(FieldText, v)) +} + +// TextHasSuffix applies the HasSuffix predicate on the "text" field. +func TextHasSuffix(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldHasSuffix(FieldText, v)) +} + +// TextEqualFold applies the EqualFold predicate on the "text" field. +func TextEqualFold(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEqualFold(FieldText, v)) +} + +// TextContainsFold applies the ContainsFold predicate on the "text" field. +func TextContainsFold(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldContainsFold(FieldText, v)) +} + +// StatusEQ applies the EQ predicate on the "status" field. +func StatusEQ(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldStatus, v)) +} + +// StatusNEQ applies the NEQ predicate on the "status" field. +func StatusNEQ(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldStatus, v)) +} + +// StatusIn applies the In predicate on the "status" field. +func StatusIn(vs ...string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldStatus, vs...)) +} + +// StatusNotIn applies the NotIn predicate on the "status" field. +func StatusNotIn(vs ...string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldStatus, vs...)) +} + +// StatusGT applies the GT predicate on the "status" field. +func StatusGT(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldStatus, v)) +} + +// StatusGTE applies the GTE predicate on the "status" field. +func StatusGTE(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldStatus, v)) +} + +// StatusLT applies the LT predicate on the "status" field. +func StatusLT(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldStatus, v)) +} + +// StatusLTE applies the LTE predicate on the "status" field. +func StatusLTE(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldStatus, v)) +} + +// StatusContains applies the Contains predicate on the "status" field. +func StatusContains(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldContains(FieldStatus, v)) +} + +// StatusHasPrefix applies the HasPrefix predicate on the "status" field. +func StatusHasPrefix(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldHasPrefix(FieldStatus, v)) +} + +// StatusHasSuffix applies the HasSuffix predicate on the "status" field. +func StatusHasSuffix(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldHasSuffix(FieldStatus, v)) +} + +// StatusEqualFold applies the EqualFold predicate on the "status" field. +func StatusEqualFold(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEqualFold(FieldStatus, v)) +} + +// StatusContainsFold applies the ContainsFold predicate on the "status" field. +func StatusContainsFold(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldContainsFold(FieldStatus, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldCreatedAt, v)) +} + +// CreatedAtIsNil applies the IsNil predicate on the "created_at" field. +func CreatedAtIsNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIsNull(FieldCreatedAt)) +} + +// CreatedAtNotNil applies the NotNil predicate on the "created_at" field. +func CreatedAtNotNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotNull(FieldCreatedAt)) +} + +// ModifiedAtEQ applies the EQ predicate on the "modified_at" field. +func ModifiedAtEQ(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldModifiedAt, v)) +} + +// ModifiedAtNEQ applies the NEQ predicate on the "modified_at" field. +func ModifiedAtNEQ(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldModifiedAt, v)) +} + +// ModifiedAtIn applies the In predicate on the "modified_at" field. +func ModifiedAtIn(vs ...time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldModifiedAt, vs...)) +} + +// ModifiedAtNotIn applies the NotIn predicate on the "modified_at" field. +func ModifiedAtNotIn(vs ...time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldModifiedAt, vs...)) +} + +// ModifiedAtGT applies the GT predicate on the "modified_at" field. +func ModifiedAtGT(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldModifiedAt, v)) +} + +// ModifiedAtGTE applies the GTE predicate on the "modified_at" field. +func ModifiedAtGTE(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldModifiedAt, v)) +} + +// ModifiedAtLT applies the LT predicate on the "modified_at" field. +func ModifiedAtLT(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldModifiedAt, v)) +} + +// ModifiedAtLTE applies the LTE predicate on the "modified_at" field. +func ModifiedAtLTE(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldModifiedAt, v)) +} + +// ModifiedAtIsNil applies the IsNil predicate on the "modified_at" field. +func ModifiedAtIsNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIsNull(FieldModifiedAt)) +} + +// ModifiedAtNotNil applies the NotNil predicate on the "modified_at" field. +func ModifiedAtNotNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotNull(FieldModifiedAt)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v time.Time) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotNull(FieldDeletedAt)) +} + +// CreatedByEQ applies the EQ predicate on the "created_by" field. +func CreatedByEQ(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldCreatedBy, v)) +} + +// CreatedByNEQ applies the NEQ predicate on the "created_by" field. +func CreatedByNEQ(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldCreatedBy, v)) +} + +// CreatedByIn applies the In predicate on the "created_by" field. +func CreatedByIn(vs ...string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldCreatedBy, vs...)) +} + +// CreatedByNotIn applies the NotIn predicate on the "created_by" field. +func CreatedByNotIn(vs ...string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldCreatedBy, vs...)) +} + +// CreatedByGT applies the GT predicate on the "created_by" field. +func CreatedByGT(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldCreatedBy, v)) +} + +// CreatedByGTE applies the GTE predicate on the "created_by" field. +func CreatedByGTE(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldCreatedBy, v)) +} + +// CreatedByLT applies the LT predicate on the "created_by" field. +func CreatedByLT(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldCreatedBy, v)) +} + +// CreatedByLTE applies the LTE predicate on the "created_by" field. +func CreatedByLTE(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldCreatedBy, v)) +} + +// CreatedByContains applies the Contains predicate on the "created_by" field. +func CreatedByContains(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldContains(FieldCreatedBy, v)) +} + +// CreatedByHasPrefix applies the HasPrefix predicate on the "created_by" field. +func CreatedByHasPrefix(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldHasPrefix(FieldCreatedBy, v)) +} + +// CreatedByHasSuffix applies the HasSuffix predicate on the "created_by" field. +func CreatedByHasSuffix(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldHasSuffix(FieldCreatedBy, v)) +} + +// CreatedByIsNil applies the IsNil predicate on the "created_by" field. +func CreatedByIsNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIsNull(FieldCreatedBy)) +} + +// CreatedByNotNil applies the NotNil predicate on the "created_by" field. +func CreatedByNotNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotNull(FieldCreatedBy)) +} + +// CreatedByEqualFold applies the EqualFold predicate on the "created_by" field. +func CreatedByEqualFold(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEqualFold(FieldCreatedBy, v)) +} + +// CreatedByContainsFold applies the ContainsFold predicate on the "created_by" field. +func CreatedByContainsFold(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldContainsFold(FieldCreatedBy, v)) +} + +// ModifiedByEQ applies the EQ predicate on the "modified_by" field. +func ModifiedByEQ(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEQ(FieldModifiedBy, v)) +} + +// ModifiedByNEQ applies the NEQ predicate on the "modified_by" field. +func ModifiedByNEQ(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNEQ(FieldModifiedBy, v)) +} + +// ModifiedByIn applies the In predicate on the "modified_by" field. +func ModifiedByIn(vs ...string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIn(FieldModifiedBy, vs...)) +} + +// ModifiedByNotIn applies the NotIn predicate on the "modified_by" field. +func ModifiedByNotIn(vs ...string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotIn(FieldModifiedBy, vs...)) +} + +// ModifiedByGT applies the GT predicate on the "modified_by" field. +func ModifiedByGT(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGT(FieldModifiedBy, v)) +} + +// ModifiedByGTE applies the GTE predicate on the "modified_by" field. +func ModifiedByGTE(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldGTE(FieldModifiedBy, v)) +} + +// ModifiedByLT applies the LT predicate on the "modified_by" field. +func ModifiedByLT(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLT(FieldModifiedBy, v)) +} + +// ModifiedByLTE applies the LTE predicate on the "modified_by" field. +func ModifiedByLTE(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldLTE(FieldModifiedBy, v)) +} + +// ModifiedByContains applies the Contains predicate on the "modified_by" field. +func ModifiedByContains(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldContains(FieldModifiedBy, v)) +} + +// ModifiedByHasPrefix applies the HasPrefix predicate on the "modified_by" field. +func ModifiedByHasPrefix(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldHasPrefix(FieldModifiedBy, v)) +} + +// ModifiedByHasSuffix applies the HasSuffix predicate on the "modified_by" field. +func ModifiedByHasSuffix(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldHasSuffix(FieldModifiedBy, v)) +} + +// ModifiedByIsNil applies the IsNil predicate on the "modified_by" field. +func ModifiedByIsNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldIsNull(FieldModifiedBy)) +} + +// ModifiedByNotNil applies the NotNil predicate on the "modified_by" field. +func ModifiedByNotNil() predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldNotNull(FieldModifiedBy)) +} + +// ModifiedByEqualFold applies the EqualFold predicate on the "modified_by" field. +func ModifiedByEqualFold(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldEqualFold(FieldModifiedBy, v)) +} + +// ModifiedByContainsFold applies the ContainsFold predicate on the "modified_by" field. +func ModifiedByContainsFold(v string) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.FieldContainsFold(FieldModifiedBy, v)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.IncidentStatus) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.IncidentStatus) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.IncidentStatus) predicate.IncidentStatus { + return predicate.IncidentStatus(sql.NotPredicates(p)) +} diff --git a/ent/incidentstatus_create.go b/ent/incidentstatus_create.go new file mode 100644 index 0000000..0b920ec --- /dev/null +++ b/ent/incidentstatus_create.go @@ -0,0 +1,1089 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" +) + +// IncidentStatusCreate is the builder for creating a IncidentStatus entity. +type IncidentStatusCreate struct { + config + mutation *IncidentStatusMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetIncidentID sets the "incident_id" field. +func (_c *IncidentStatusCreate) SetIncidentID(v int) *IncidentStatusCreate { + _c.mutation.SetIncidentID(v) + return _c +} + +// SetNillableIncidentID sets the "incident_id" field if the given value is not nil. +func (_c *IncidentStatusCreate) SetNillableIncidentID(v *int) *IncidentStatusCreate { + if v != nil { + _c.SetIncidentID(*v) + } + return _c +} + +// SetTimestamp sets the "timestamp" field. +func (_c *IncidentStatusCreate) SetTimestamp(v time.Time) *IncidentStatusCreate { + _c.mutation.SetTimestamp(v) + return _c +} + +// SetText sets the "text" field. +func (_c *IncidentStatusCreate) SetText(v string) *IncidentStatusCreate { + _c.mutation.SetText(v) + return _c +} + +// SetStatus sets the "status" field. +func (_c *IncidentStatusCreate) SetStatus(v string) *IncidentStatusCreate { + _c.mutation.SetStatus(v) + return _c +} + +// SetCreatedAt sets the "created_at" field. +func (_c *IncidentStatusCreate) SetCreatedAt(v time.Time) *IncidentStatusCreate { + _c.mutation.SetCreatedAt(v) + return _c +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_c *IncidentStatusCreate) SetNillableCreatedAt(v *time.Time) *IncidentStatusCreate { + if v != nil { + _c.SetCreatedAt(*v) + } + return _c +} + +// SetModifiedAt sets the "modified_at" field. +func (_c *IncidentStatusCreate) SetModifiedAt(v time.Time) *IncidentStatusCreate { + _c.mutation.SetModifiedAt(v) + return _c +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_c *IncidentStatusCreate) SetNillableModifiedAt(v *time.Time) *IncidentStatusCreate { + if v != nil { + _c.SetModifiedAt(*v) + } + return _c +} + +// SetDeletedAt sets the "deleted_at" field. +func (_c *IncidentStatusCreate) SetDeletedAt(v time.Time) *IncidentStatusCreate { + _c.mutation.SetDeletedAt(v) + return _c +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_c *IncidentStatusCreate) SetNillableDeletedAt(v *time.Time) *IncidentStatusCreate { + if v != nil { + _c.SetDeletedAt(*v) + } + return _c +} + +// SetCreatedBy sets the "created_by" field. +func (_c *IncidentStatusCreate) SetCreatedBy(v string) *IncidentStatusCreate { + _c.mutation.SetCreatedBy(v) + return _c +} + +// SetNillableCreatedBy sets the "created_by" field if the given value is not nil. +func (_c *IncidentStatusCreate) SetNillableCreatedBy(v *string) *IncidentStatusCreate { + if v != nil { + _c.SetCreatedBy(*v) + } + return _c +} + +// SetModifiedBy sets the "modified_by" field. +func (_c *IncidentStatusCreate) SetModifiedBy(v string) *IncidentStatusCreate { + _c.mutation.SetModifiedBy(v) + return _c +} + +// SetNillableModifiedBy sets the "modified_by" field if the given value is not nil. +func (_c *IncidentStatusCreate) SetNillableModifiedBy(v *string) *IncidentStatusCreate { + if v != nil { + _c.SetModifiedBy(*v) + } + return _c +} + +// SetID sets the "id" field. +func (_c *IncidentStatusCreate) SetID(v int) *IncidentStatusCreate { + _c.mutation.SetID(v) + return _c +} + +// Mutation returns the IncidentStatusMutation object of the builder. +func (_c *IncidentStatusCreate) Mutation() *IncidentStatusMutation { + return _c.mutation +} + +// Save creates the IncidentStatus in the database. +func (_c *IncidentStatusCreate) Save(ctx context.Context) (*IncidentStatus, error) { + return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (_c *IncidentStatusCreate) SaveX(ctx context.Context) *IncidentStatus { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *IncidentStatusCreate) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *IncidentStatusCreate) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_c *IncidentStatusCreate) check() error { + if _, ok := _c.mutation.Timestamp(); !ok { + return &ValidationError{Name: "timestamp", err: errors.New(`ent: missing required field "IncidentStatus.timestamp"`)} + } + if _, ok := _c.mutation.Text(); !ok { + return &ValidationError{Name: "text", err: errors.New(`ent: missing required field "IncidentStatus.text"`)} + } + if v, ok := _c.mutation.Text(); ok { + if err := incidentstatus.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "IncidentStatus.text": %w`, err)} + } + } + if _, ok := _c.mutation.Status(); !ok { + return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "IncidentStatus.status"`)} + } + if v, ok := _c.mutation.Status(); ok { + if err := incidentstatus.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "IncidentStatus.status": %w`, err)} + } + } + return nil +} + +func (_c *IncidentStatusCreate) sqlSave(ctx context.Context) (*IncidentStatus, error) { + if err := _c.check(); err != nil { + return nil, err + } + _node, _spec := _c.createSpec() + if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int(id) + } + _c.mutation.id = &_node.ID + _c.mutation.done = true + return _node, nil +} + +func (_c *IncidentStatusCreate) createSpec() (*IncidentStatus, *sqlgraph.CreateSpec) { + var ( + _node = &IncidentStatus{config: _c.config} + _spec = sqlgraph.NewCreateSpec(incidentstatus.Table, sqlgraph.NewFieldSpec(incidentstatus.FieldID, field.TypeInt)) + ) + _spec.OnConflict = _c.conflict + if id, ok := _c.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := _c.mutation.IncidentID(); ok { + _spec.SetField(incidentstatus.FieldIncidentID, field.TypeInt, value) + _node.IncidentID = value + } + if value, ok := _c.mutation.Timestamp(); ok { + _spec.SetField(incidentstatus.FieldTimestamp, field.TypeTime, value) + _node.Timestamp = value + } + if value, ok := _c.mutation.Text(); ok { + _spec.SetField(incidentstatus.FieldText, field.TypeString, value) + _node.Text = value + } + if value, ok := _c.mutation.Status(); ok { + _spec.SetField(incidentstatus.FieldStatus, field.TypeString, value) + _node.Status = value + } + if value, ok := _c.mutation.CreatedAt(); ok { + _spec.SetField(incidentstatus.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := _c.mutation.ModifiedAt(); ok { + _spec.SetField(incidentstatus.FieldModifiedAt, field.TypeTime, value) + _node.ModifiedAt = value + } + if value, ok := _c.mutation.DeletedAt(); ok { + _spec.SetField(incidentstatus.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = value + } + if value, ok := _c.mutation.CreatedBy(); ok { + _spec.SetField(incidentstatus.FieldCreatedBy, field.TypeString, value) + _node.CreatedBy = value + } + if value, ok := _c.mutation.ModifiedBy(); ok { + _spec.SetField(incidentstatus.FieldModifiedBy, field.TypeString, value) + _node.ModifiedBy = value + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.IncidentStatus.Create(). +// SetIncidentID(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.IncidentStatusUpsert) { +// SetIncidentID(v+v). +// }). +// Exec(ctx) +func (_c *IncidentStatusCreate) OnConflict(opts ...sql.ConflictOption) *IncidentStatusUpsertOne { + _c.conflict = opts + return &IncidentStatusUpsertOne{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.IncidentStatus.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *IncidentStatusCreate) OnConflictColumns(columns ...string) *IncidentStatusUpsertOne { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &IncidentStatusUpsertOne{ + create: _c, + } +} + +type ( + // IncidentStatusUpsertOne is the builder for "upsert"-ing + // one IncidentStatus node. + IncidentStatusUpsertOne struct { + create *IncidentStatusCreate + } + + // IncidentStatusUpsert is the "OnConflict" setter. + IncidentStatusUpsert struct { + *sql.UpdateSet + } +) + +// SetIncidentID sets the "incident_id" field. +func (u *IncidentStatusUpsert) SetIncidentID(v int) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldIncidentID, v) + return u +} + +// UpdateIncidentID sets the "incident_id" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateIncidentID() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldIncidentID) + return u +} + +// AddIncidentID adds v to the "incident_id" field. +func (u *IncidentStatusUpsert) AddIncidentID(v int) *IncidentStatusUpsert { + u.Add(incidentstatus.FieldIncidentID, v) + return u +} + +// ClearIncidentID clears the value of the "incident_id" field. +func (u *IncidentStatusUpsert) ClearIncidentID() *IncidentStatusUpsert { + u.SetNull(incidentstatus.FieldIncidentID) + return u +} + +// SetTimestamp sets the "timestamp" field. +func (u *IncidentStatusUpsert) SetTimestamp(v time.Time) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldTimestamp, v) + return u +} + +// UpdateTimestamp sets the "timestamp" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateTimestamp() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldTimestamp) + return u +} + +// SetText sets the "text" field. +func (u *IncidentStatusUpsert) SetText(v string) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldText, v) + return u +} + +// UpdateText sets the "text" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateText() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldText) + return u +} + +// SetStatus sets the "status" field. +func (u *IncidentStatusUpsert) SetStatus(v string) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldStatus, v) + return u +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateStatus() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldStatus) + return u +} + +// SetCreatedAt sets the "created_at" field. +func (u *IncidentStatusUpsert) SetCreatedAt(v time.Time) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldCreatedAt, v) + return u +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateCreatedAt() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldCreatedAt) + return u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *IncidentStatusUpsert) ClearCreatedAt() *IncidentStatusUpsert { + u.SetNull(incidentstatus.FieldCreatedAt) + return u +} + +// SetModifiedAt sets the "modified_at" field. +func (u *IncidentStatusUpsert) SetModifiedAt(v time.Time) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldModifiedAt, v) + return u +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateModifiedAt() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldModifiedAt) + return u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *IncidentStatusUpsert) ClearModifiedAt() *IncidentStatusUpsert { + u.SetNull(incidentstatus.FieldModifiedAt) + return u +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *IncidentStatusUpsert) SetDeletedAt(v time.Time) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldDeletedAt, v) + return u +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateDeletedAt() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldDeletedAt) + return u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *IncidentStatusUpsert) ClearDeletedAt() *IncidentStatusUpsert { + u.SetNull(incidentstatus.FieldDeletedAt) + return u +} + +// SetCreatedBy sets the "created_by" field. +func (u *IncidentStatusUpsert) SetCreatedBy(v string) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldCreatedBy, v) + return u +} + +// UpdateCreatedBy sets the "created_by" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateCreatedBy() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldCreatedBy) + return u +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (u *IncidentStatusUpsert) ClearCreatedBy() *IncidentStatusUpsert { + u.SetNull(incidentstatus.FieldCreatedBy) + return u +} + +// SetModifiedBy sets the "modified_by" field. +func (u *IncidentStatusUpsert) SetModifiedBy(v string) *IncidentStatusUpsert { + u.Set(incidentstatus.FieldModifiedBy, v) + return u +} + +// UpdateModifiedBy sets the "modified_by" field to the value that was provided on create. +func (u *IncidentStatusUpsert) UpdateModifiedBy() *IncidentStatusUpsert { + u.SetExcluded(incidentstatus.FieldModifiedBy) + return u +} + +// ClearModifiedBy clears the value of the "modified_by" field. +func (u *IncidentStatusUpsert) ClearModifiedBy() *IncidentStatusUpsert { + u.SetNull(incidentstatus.FieldModifiedBy) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. +// Using this option is equivalent to using: +// +// client.IncidentStatus.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(incidentstatus.FieldID) +// }), +// ). +// Exec(ctx) +func (u *IncidentStatusUpsertOne) UpdateNewValues() *IncidentStatusUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.ID(); exists { + s.SetIgnore(incidentstatus.FieldID) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.IncidentStatus.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *IncidentStatusUpsertOne) Ignore() *IncidentStatusUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *IncidentStatusUpsertOne) DoNothing() *IncidentStatusUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the IncidentStatusCreate.OnConflict +// documentation for more info. +func (u *IncidentStatusUpsertOne) Update(set func(*IncidentStatusUpsert)) *IncidentStatusUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&IncidentStatusUpsert{UpdateSet: update}) + })) + return u +} + +// SetIncidentID sets the "incident_id" field. +func (u *IncidentStatusUpsertOne) SetIncidentID(v int) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetIncidentID(v) + }) +} + +// AddIncidentID adds v to the "incident_id" field. +func (u *IncidentStatusUpsertOne) AddIncidentID(v int) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.AddIncidentID(v) + }) +} + +// UpdateIncidentID sets the "incident_id" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateIncidentID() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateIncidentID() + }) +} + +// ClearIncidentID clears the value of the "incident_id" field. +func (u *IncidentStatusUpsertOne) ClearIncidentID() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearIncidentID() + }) +} + +// SetTimestamp sets the "timestamp" field. +func (u *IncidentStatusUpsertOne) SetTimestamp(v time.Time) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetTimestamp(v) + }) +} + +// UpdateTimestamp sets the "timestamp" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateTimestamp() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateTimestamp() + }) +} + +// SetText sets the "text" field. +func (u *IncidentStatusUpsertOne) SetText(v string) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetText(v) + }) +} + +// UpdateText sets the "text" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateText() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateText() + }) +} + +// SetStatus sets the "status" field. +func (u *IncidentStatusUpsertOne) SetStatus(v string) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateStatus() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateStatus() + }) +} + +// SetCreatedAt sets the "created_at" field. +func (u *IncidentStatusUpsertOne) SetCreatedAt(v time.Time) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateCreatedAt() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateCreatedAt() + }) +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *IncidentStatusUpsertOne) ClearCreatedAt() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearCreatedAt() + }) +} + +// SetModifiedAt sets the "modified_at" field. +func (u *IncidentStatusUpsertOne) SetModifiedAt(v time.Time) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetModifiedAt(v) + }) +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateModifiedAt() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateModifiedAt() + }) +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *IncidentStatusUpsertOne) ClearModifiedAt() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearModifiedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *IncidentStatusUpsertOne) SetDeletedAt(v time.Time) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateDeletedAt() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *IncidentStatusUpsertOne) ClearDeletedAt() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearDeletedAt() + }) +} + +// SetCreatedBy sets the "created_by" field. +func (u *IncidentStatusUpsertOne) SetCreatedBy(v string) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetCreatedBy(v) + }) +} + +// UpdateCreatedBy sets the "created_by" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateCreatedBy() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateCreatedBy() + }) +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (u *IncidentStatusUpsertOne) ClearCreatedBy() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearCreatedBy() + }) +} + +// SetModifiedBy sets the "modified_by" field. +func (u *IncidentStatusUpsertOne) SetModifiedBy(v string) *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetModifiedBy(v) + }) +} + +// UpdateModifiedBy sets the "modified_by" field to the value that was provided on create. +func (u *IncidentStatusUpsertOne) UpdateModifiedBy() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateModifiedBy() + }) +} + +// ClearModifiedBy clears the value of the "modified_by" field. +func (u *IncidentStatusUpsertOne) ClearModifiedBy() *IncidentStatusUpsertOne { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearModifiedBy() + }) +} + +// Exec executes the query. +func (u *IncidentStatusUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for IncidentStatusCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *IncidentStatusUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *IncidentStatusUpsertOne) ID(ctx context.Context) (id int, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *IncidentStatusUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// IncidentStatusCreateBulk is the builder for creating many IncidentStatus entities in bulk. +type IncidentStatusCreateBulk struct { + config + err error + builders []*IncidentStatusCreate + conflict []sql.ConflictOption +} + +// Save creates the IncidentStatus entities in the database. +func (_c *IncidentStatusCreateBulk) Save(ctx context.Context) ([]*IncidentStatus, error) { + if _c.err != nil { + return nil, _c.err + } + specs := make([]*sqlgraph.CreateSpec, len(_c.builders)) + nodes := make([]*IncidentStatus, len(_c.builders)) + mutators := make([]Mutator, len(_c.builders)) + for i := range _c.builders { + func(i int, root context.Context) { + builder := _c.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*IncidentStatusMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = _c.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (_c *IncidentStatusCreateBulk) SaveX(ctx context.Context) []*IncidentStatus { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *IncidentStatusCreateBulk) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *IncidentStatusCreateBulk) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.IncidentStatus.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.IncidentStatusUpsert) { +// SetIncidentID(v+v). +// }). +// Exec(ctx) +func (_c *IncidentStatusCreateBulk) OnConflict(opts ...sql.ConflictOption) *IncidentStatusUpsertBulk { + _c.conflict = opts + return &IncidentStatusUpsertBulk{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.IncidentStatus.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *IncidentStatusCreateBulk) OnConflictColumns(columns ...string) *IncidentStatusUpsertBulk { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &IncidentStatusUpsertBulk{ + create: _c, + } +} + +// IncidentStatusUpsertBulk is the builder for "upsert"-ing +// a bulk of IncidentStatus nodes. +type IncidentStatusUpsertBulk struct { + create *IncidentStatusCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.IncidentStatus.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(incidentstatus.FieldID) +// }), +// ). +// Exec(ctx) +func (u *IncidentStatusUpsertBulk) UpdateNewValues() *IncidentStatusUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.ID(); exists { + s.SetIgnore(incidentstatus.FieldID) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.IncidentStatus.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *IncidentStatusUpsertBulk) Ignore() *IncidentStatusUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *IncidentStatusUpsertBulk) DoNothing() *IncidentStatusUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the IncidentStatusCreateBulk.OnConflict +// documentation for more info. +func (u *IncidentStatusUpsertBulk) Update(set func(*IncidentStatusUpsert)) *IncidentStatusUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&IncidentStatusUpsert{UpdateSet: update}) + })) + return u +} + +// SetIncidentID sets the "incident_id" field. +func (u *IncidentStatusUpsertBulk) SetIncidentID(v int) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetIncidentID(v) + }) +} + +// AddIncidentID adds v to the "incident_id" field. +func (u *IncidentStatusUpsertBulk) AddIncidentID(v int) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.AddIncidentID(v) + }) +} + +// UpdateIncidentID sets the "incident_id" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateIncidentID() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateIncidentID() + }) +} + +// ClearIncidentID clears the value of the "incident_id" field. +func (u *IncidentStatusUpsertBulk) ClearIncidentID() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearIncidentID() + }) +} + +// SetTimestamp sets the "timestamp" field. +func (u *IncidentStatusUpsertBulk) SetTimestamp(v time.Time) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetTimestamp(v) + }) +} + +// UpdateTimestamp sets the "timestamp" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateTimestamp() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateTimestamp() + }) +} + +// SetText sets the "text" field. +func (u *IncidentStatusUpsertBulk) SetText(v string) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetText(v) + }) +} + +// UpdateText sets the "text" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateText() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateText() + }) +} + +// SetStatus sets the "status" field. +func (u *IncidentStatusUpsertBulk) SetStatus(v string) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateStatus() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateStatus() + }) +} + +// SetCreatedAt sets the "created_at" field. +func (u *IncidentStatusUpsertBulk) SetCreatedAt(v time.Time) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateCreatedAt() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateCreatedAt() + }) +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (u *IncidentStatusUpsertBulk) ClearCreatedAt() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearCreatedAt() + }) +} + +// SetModifiedAt sets the "modified_at" field. +func (u *IncidentStatusUpsertBulk) SetModifiedAt(v time.Time) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetModifiedAt(v) + }) +} + +// UpdateModifiedAt sets the "modified_at" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateModifiedAt() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateModifiedAt() + }) +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (u *IncidentStatusUpsertBulk) ClearModifiedAt() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearModifiedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *IncidentStatusUpsertBulk) SetDeletedAt(v time.Time) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateDeletedAt() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *IncidentStatusUpsertBulk) ClearDeletedAt() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearDeletedAt() + }) +} + +// SetCreatedBy sets the "created_by" field. +func (u *IncidentStatusUpsertBulk) SetCreatedBy(v string) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetCreatedBy(v) + }) +} + +// UpdateCreatedBy sets the "created_by" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateCreatedBy() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateCreatedBy() + }) +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (u *IncidentStatusUpsertBulk) ClearCreatedBy() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearCreatedBy() + }) +} + +// SetModifiedBy sets the "modified_by" field. +func (u *IncidentStatusUpsertBulk) SetModifiedBy(v string) *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.SetModifiedBy(v) + }) +} + +// UpdateModifiedBy sets the "modified_by" field to the value that was provided on create. +func (u *IncidentStatusUpsertBulk) UpdateModifiedBy() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.UpdateModifiedBy() + }) +} + +// ClearModifiedBy clears the value of the "modified_by" field. +func (u *IncidentStatusUpsertBulk) ClearModifiedBy() *IncidentStatusUpsertBulk { + return u.Update(func(s *IncidentStatusUpsert) { + s.ClearModifiedBy() + }) +} + +// Exec executes the query. +func (u *IncidentStatusUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the IncidentStatusCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for IncidentStatusCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *IncidentStatusUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/incidentstatus_delete.go b/ent/incidentstatus_delete.go new file mode 100644 index 0000000..b15d652 --- /dev/null +++ b/ent/incidentstatus_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// IncidentStatusDelete is the builder for deleting a IncidentStatus entity. +type IncidentStatusDelete struct { + config + hooks []Hook + mutation *IncidentStatusMutation +} + +// Where appends a list predicates to the IncidentStatusDelete builder. +func (_d *IncidentStatusDelete) Where(ps ...predicate.IncidentStatus) *IncidentStatusDelete { + _d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (_d *IncidentStatusDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *IncidentStatusDelete) ExecX(ctx context.Context) int { + n, err := _d.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (_d *IncidentStatusDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(incidentstatus.Table, sqlgraph.NewFieldSpec(incidentstatus.FieldID, field.TypeInt)) + if ps := _d.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + _d.mutation.done = true + return affected, err +} + +// IncidentStatusDeleteOne is the builder for deleting a single IncidentStatus entity. +type IncidentStatusDeleteOne struct { + _d *IncidentStatusDelete +} + +// Where appends a list predicates to the IncidentStatusDelete builder. +func (_d *IncidentStatusDeleteOne) Where(ps ...predicate.IncidentStatus) *IncidentStatusDeleteOne { + _d._d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query. +func (_d *IncidentStatusDeleteOne) Exec(ctx context.Context) error { + n, err := _d._d.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{incidentstatus.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *IncidentStatusDeleteOne) ExecX(ctx context.Context) { + if err := _d.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/incidentstatus_query.go b/ent/incidentstatus_query.go new file mode 100644 index 0000000..a2ac008 --- /dev/null +++ b/ent/incidentstatus_query.go @@ -0,0 +1,527 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// IncidentStatusQuery is the builder for querying IncidentStatus entities. +type IncidentStatusQuery struct { + config + ctx *QueryContext + order []incidentstatus.OrderOption + inters []Interceptor + predicates []predicate.IncidentStatus + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the IncidentStatusQuery builder. +func (_q *IncidentStatusQuery) Where(ps ...predicate.IncidentStatus) *IncidentStatusQuery { + _q.predicates = append(_q.predicates, ps...) + return _q +} + +// Limit the number of records to be returned by this query. +func (_q *IncidentStatusQuery) Limit(limit int) *IncidentStatusQuery { + _q.ctx.Limit = &limit + return _q +} + +// Offset to start from. +func (_q *IncidentStatusQuery) Offset(offset int) *IncidentStatusQuery { + _q.ctx.Offset = &offset + return _q +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (_q *IncidentStatusQuery) Unique(unique bool) *IncidentStatusQuery { + _q.ctx.Unique = &unique + return _q +} + +// Order specifies how the records should be ordered. +func (_q *IncidentStatusQuery) Order(o ...incidentstatus.OrderOption) *IncidentStatusQuery { + _q.order = append(_q.order, o...) + return _q +} + +// First returns the first IncidentStatus entity from the query. +// Returns a *NotFoundError when no IncidentStatus was found. +func (_q *IncidentStatusQuery) First(ctx context.Context) (*IncidentStatus, error) { + nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{incidentstatus.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (_q *IncidentStatusQuery) FirstX(ctx context.Context) *IncidentStatus { + node, err := _q.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first IncidentStatus ID from the query. +// Returns a *NotFoundError when no IncidentStatus ID was found. +func (_q *IncidentStatusQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{incidentstatus.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (_q *IncidentStatusQuery) FirstIDX(ctx context.Context) int { + id, err := _q.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single IncidentStatus entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one IncidentStatus entity is found. +// Returns a *NotFoundError when no IncidentStatus entities are found. +func (_q *IncidentStatusQuery) Only(ctx context.Context) (*IncidentStatus, error) { + nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{incidentstatus.Label} + default: + return nil, &NotSingularError{incidentstatus.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (_q *IncidentStatusQuery) OnlyX(ctx context.Context) *IncidentStatus { + node, err := _q.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only IncidentStatus ID in the query. +// Returns a *NotSingularError when more than one IncidentStatus ID is found. +// Returns a *NotFoundError when no entities are found. +func (_q *IncidentStatusQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{incidentstatus.Label} + default: + err = &NotSingularError{incidentstatus.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (_q *IncidentStatusQuery) OnlyIDX(ctx context.Context) int { + id, err := _q.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of IncidentStatusSlice. +func (_q *IncidentStatusQuery) All(ctx context.Context) ([]*IncidentStatus, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll) + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*IncidentStatus, *IncidentStatusQuery]() + return withInterceptors[[]*IncidentStatus](ctx, _q, qr, _q.inters) +} + +// AllX is like All, but panics if an error occurs. +func (_q *IncidentStatusQuery) AllX(ctx context.Context) []*IncidentStatus { + nodes, err := _q.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of IncidentStatus IDs. +func (_q *IncidentStatusQuery) IDs(ctx context.Context) (ids []int, err error) { + if _q.ctx.Unique == nil && _q.path != nil { + _q.Unique(true) + } + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs) + if err = _q.Select(incidentstatus.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (_q *IncidentStatusQuery) IDsX(ctx context.Context) []int { + ids, err := _q.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (_q *IncidentStatusQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount) + if err := _q.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, _q, querierCount[*IncidentStatusQuery](), _q.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (_q *IncidentStatusQuery) CountX(ctx context.Context) int { + count, err := _q.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (_q *IncidentStatusQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist) + switch _, err := _q.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (_q *IncidentStatusQuery) ExistX(ctx context.Context) bool { + exist, err := _q.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the IncidentStatusQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (_q *IncidentStatusQuery) Clone() *IncidentStatusQuery { + if _q == nil { + return nil + } + return &IncidentStatusQuery{ + config: _q.config, + ctx: _q.ctx.Clone(), + order: append([]incidentstatus.OrderOption{}, _q.order...), + inters: append([]Interceptor{}, _q.inters...), + predicates: append([]predicate.IncidentStatus{}, _q.predicates...), + // clone intermediate query. + sql: _q.sql.Clone(), + path: _q.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// IncidentID int `json:"incident_id,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.IncidentStatus.Query(). +// GroupBy(incidentstatus.FieldIncidentID). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (_q *IncidentStatusQuery) GroupBy(field string, fields ...string) *IncidentStatusGroupBy { + _q.ctx.Fields = append([]string{field}, fields...) + grbuild := &IncidentStatusGroupBy{build: _q} + grbuild.flds = &_q.ctx.Fields + grbuild.label = incidentstatus.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// IncidentID int `json:"incident_id,omitempty"` +// } +// +// client.IncidentStatus.Query(). +// Select(incidentstatus.FieldIncidentID). +// Scan(ctx, &v) +func (_q *IncidentStatusQuery) Select(fields ...string) *IncidentStatusSelect { + _q.ctx.Fields = append(_q.ctx.Fields, fields...) + sbuild := &IncidentStatusSelect{IncidentStatusQuery: _q} + sbuild.label = incidentstatus.Label + sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a IncidentStatusSelect configured with the given aggregations. +func (_q *IncidentStatusQuery) Aggregate(fns ...AggregateFunc) *IncidentStatusSelect { + return _q.Select().Aggregate(fns...) +} + +func (_q *IncidentStatusQuery) prepareQuery(ctx context.Context) error { + for _, inter := range _q.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, _q); err != nil { + return err + } + } + } + for _, f := range _q.ctx.Fields { + if !incidentstatus.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if _q.path != nil { + prev, err := _q.path(ctx) + if err != nil { + return err + } + _q.sql = prev + } + return nil +} + +func (_q *IncidentStatusQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*IncidentStatus, error) { + var ( + nodes = []*IncidentStatus{} + _spec = _q.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*IncidentStatus).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &IncidentStatus{config: _q.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (_q *IncidentStatusQuery) sqlCount(ctx context.Context) (int, error) { + _spec := _q.querySpec() + _spec.Node.Columns = _q.ctx.Fields + if len(_q.ctx.Fields) > 0 { + _spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique + } + return sqlgraph.CountNodes(ctx, _q.driver, _spec) +} + +func (_q *IncidentStatusQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(incidentstatus.Table, incidentstatus.Columns, sqlgraph.NewFieldSpec(incidentstatus.FieldID, field.TypeInt)) + _spec.From = _q.sql + if unique := _q.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if _q.path != nil { + _spec.Unique = true + } + if fields := _q.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, incidentstatus.FieldID) + for i := range fields { + if fields[i] != incidentstatus.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := _q.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := _q.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := _q.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := _q.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (_q *IncidentStatusQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(_q.driver.Dialect()) + t1 := builder.Table(incidentstatus.Table) + columns := _q.ctx.Fields + if len(columns) == 0 { + columns = incidentstatus.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if _q.sql != nil { + selector = _q.sql + selector.Select(selector.Columns(columns...)...) + } + if _q.ctx.Unique != nil && *_q.ctx.Unique { + selector.Distinct() + } + for _, p := range _q.predicates { + p(selector) + } + for _, p := range _q.order { + p(selector) + } + if offset := _q.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := _q.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// IncidentStatusGroupBy is the group-by builder for IncidentStatus entities. +type IncidentStatusGroupBy struct { + selector + build *IncidentStatusQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (_g *IncidentStatusGroupBy) Aggregate(fns ...AggregateFunc) *IncidentStatusGroupBy { + _g.fns = append(_g.fns, fns...) + return _g +} + +// Scan applies the selector query and scans the result into the given value. +func (_g *IncidentStatusGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy) + if err := _g.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*IncidentStatusQuery, *IncidentStatusGroupBy](ctx, _g.build, _g, _g.build.inters, v) +} + +func (_g *IncidentStatusGroupBy) sqlScan(ctx context.Context, root *IncidentStatusQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(_g.fns)) + for _, fn := range _g.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*_g.flds)+len(_g.fns)) + for _, f := range *_g.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*_g.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _g.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// IncidentStatusSelect is the builder for selecting fields of IncidentStatus entities. +type IncidentStatusSelect struct { + *IncidentStatusQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (_s *IncidentStatusSelect) Aggregate(fns ...AggregateFunc) *IncidentStatusSelect { + _s.fns = append(_s.fns, fns...) + return _s +} + +// Scan applies the selector query and scans the result into the given value. +func (_s *IncidentStatusSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect) + if err := _s.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*IncidentStatusQuery, *IncidentStatusSelect](ctx, _s.IncidentStatusQuery, _s, _s.inters, v) +} + +func (_s *IncidentStatusSelect) sqlScan(ctx context.Context, root *IncidentStatusQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(_s.fns)) + for _, fn := range _s.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*_s.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _s.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/incidentstatus_update.go b/ent/incidentstatus_update.go new file mode 100644 index 0000000..7115ef2 --- /dev/null +++ b/ent/incidentstatus_update.go @@ -0,0 +1,646 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// IncidentStatusUpdate is the builder for updating IncidentStatus entities. +type IncidentStatusUpdate struct { + config + hooks []Hook + mutation *IncidentStatusMutation +} + +// Where appends a list predicates to the IncidentStatusUpdate builder. +func (_u *IncidentStatusUpdate) Where(ps ...predicate.IncidentStatus) *IncidentStatusUpdate { + _u.mutation.Where(ps...) + return _u +} + +// SetIncidentID sets the "incident_id" field. +func (_u *IncidentStatusUpdate) SetIncidentID(v int) *IncidentStatusUpdate { + _u.mutation.ResetIncidentID() + _u.mutation.SetIncidentID(v) + return _u +} + +// SetNillableIncidentID sets the "incident_id" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableIncidentID(v *int) *IncidentStatusUpdate { + if v != nil { + _u.SetIncidentID(*v) + } + return _u +} + +// AddIncidentID adds value to the "incident_id" field. +func (_u *IncidentStatusUpdate) AddIncidentID(v int) *IncidentStatusUpdate { + _u.mutation.AddIncidentID(v) + return _u +} + +// ClearIncidentID clears the value of the "incident_id" field. +func (_u *IncidentStatusUpdate) ClearIncidentID() *IncidentStatusUpdate { + _u.mutation.ClearIncidentID() + return _u +} + +// SetTimestamp sets the "timestamp" field. +func (_u *IncidentStatusUpdate) SetTimestamp(v time.Time) *IncidentStatusUpdate { + _u.mutation.SetTimestamp(v) + return _u +} + +// SetNillableTimestamp sets the "timestamp" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableTimestamp(v *time.Time) *IncidentStatusUpdate { + if v != nil { + _u.SetTimestamp(*v) + } + return _u +} + +// SetText sets the "text" field. +func (_u *IncidentStatusUpdate) SetText(v string) *IncidentStatusUpdate { + _u.mutation.SetText(v) + return _u +} + +// SetNillableText sets the "text" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableText(v *string) *IncidentStatusUpdate { + if v != nil { + _u.SetText(*v) + } + return _u +} + +// SetStatus sets the "status" field. +func (_u *IncidentStatusUpdate) SetStatus(v string) *IncidentStatusUpdate { + _u.mutation.SetStatus(v) + return _u +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableStatus(v *string) *IncidentStatusUpdate { + if v != nil { + _u.SetStatus(*v) + } + return _u +} + +// SetCreatedAt sets the "created_at" field. +func (_u *IncidentStatusUpdate) SetCreatedAt(v time.Time) *IncidentStatusUpdate { + _u.mutation.SetCreatedAt(v) + return _u +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableCreatedAt(v *time.Time) *IncidentStatusUpdate { + if v != nil { + _u.SetCreatedAt(*v) + } + return _u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (_u *IncidentStatusUpdate) ClearCreatedAt() *IncidentStatusUpdate { + _u.mutation.ClearCreatedAt() + return _u +} + +// SetModifiedAt sets the "modified_at" field. +func (_u *IncidentStatusUpdate) SetModifiedAt(v time.Time) *IncidentStatusUpdate { + _u.mutation.SetModifiedAt(v) + return _u +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableModifiedAt(v *time.Time) *IncidentStatusUpdate { + if v != nil { + _u.SetModifiedAt(*v) + } + return _u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (_u *IncidentStatusUpdate) ClearModifiedAt() *IncidentStatusUpdate { + _u.mutation.ClearModifiedAt() + return _u +} + +// SetDeletedAt sets the "deleted_at" field. +func (_u *IncidentStatusUpdate) SetDeletedAt(v time.Time) *IncidentStatusUpdate { + _u.mutation.SetDeletedAt(v) + return _u +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableDeletedAt(v *time.Time) *IncidentStatusUpdate { + if v != nil { + _u.SetDeletedAt(*v) + } + return _u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (_u *IncidentStatusUpdate) ClearDeletedAt() *IncidentStatusUpdate { + _u.mutation.ClearDeletedAt() + return _u +} + +// SetCreatedBy sets the "created_by" field. +func (_u *IncidentStatusUpdate) SetCreatedBy(v string) *IncidentStatusUpdate { + _u.mutation.SetCreatedBy(v) + return _u +} + +// SetNillableCreatedBy sets the "created_by" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableCreatedBy(v *string) *IncidentStatusUpdate { + if v != nil { + _u.SetCreatedBy(*v) + } + return _u +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (_u *IncidentStatusUpdate) ClearCreatedBy() *IncidentStatusUpdate { + _u.mutation.ClearCreatedBy() + return _u +} + +// SetModifiedBy sets the "modified_by" field. +func (_u *IncidentStatusUpdate) SetModifiedBy(v string) *IncidentStatusUpdate { + _u.mutation.SetModifiedBy(v) + return _u +} + +// SetNillableModifiedBy sets the "modified_by" field if the given value is not nil. +func (_u *IncidentStatusUpdate) SetNillableModifiedBy(v *string) *IncidentStatusUpdate { + if v != nil { + _u.SetModifiedBy(*v) + } + return _u +} + +// ClearModifiedBy clears the value of the "modified_by" field. +func (_u *IncidentStatusUpdate) ClearModifiedBy() *IncidentStatusUpdate { + _u.mutation.ClearModifiedBy() + return _u +} + +// Mutation returns the IncidentStatusMutation object of the builder. +func (_u *IncidentStatusUpdate) Mutation() *IncidentStatusMutation { + return _u.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (_u *IncidentStatusUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *IncidentStatusUpdate) SaveX(ctx context.Context) int { + affected, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (_u *IncidentStatusUpdate) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *IncidentStatusUpdate) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *IncidentStatusUpdate) check() error { + if v, ok := _u.mutation.Text(); ok { + if err := incidentstatus.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "IncidentStatus.text": %w`, err)} + } + } + if v, ok := _u.mutation.Status(); ok { + if err := incidentstatus.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "IncidentStatus.status": %w`, err)} + } + } + return nil +} + +func (_u *IncidentStatusUpdate) sqlSave(ctx context.Context) (_node int, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(incidentstatus.Table, incidentstatus.Columns, sqlgraph.NewFieldSpec(incidentstatus.FieldID, field.TypeInt)) + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.IncidentID(); ok { + _spec.SetField(incidentstatus.FieldIncidentID, field.TypeInt, value) + } + if value, ok := _u.mutation.AddedIncidentID(); ok { + _spec.AddField(incidentstatus.FieldIncidentID, field.TypeInt, value) + } + if _u.mutation.IncidentIDCleared() { + _spec.ClearField(incidentstatus.FieldIncidentID, field.TypeInt) + } + if value, ok := _u.mutation.Timestamp(); ok { + _spec.SetField(incidentstatus.FieldTimestamp, field.TypeTime, value) + } + if value, ok := _u.mutation.Text(); ok { + _spec.SetField(incidentstatus.FieldText, field.TypeString, value) + } + if value, ok := _u.mutation.Status(); ok { + _spec.SetField(incidentstatus.FieldStatus, field.TypeString, value) + } + if value, ok := _u.mutation.CreatedAt(); ok { + _spec.SetField(incidentstatus.FieldCreatedAt, field.TypeTime, value) + } + if _u.mutation.CreatedAtCleared() { + _spec.ClearField(incidentstatus.FieldCreatedAt, field.TypeTime) + } + if value, ok := _u.mutation.ModifiedAt(); ok { + _spec.SetField(incidentstatus.FieldModifiedAt, field.TypeTime, value) + } + if _u.mutation.ModifiedAtCleared() { + _spec.ClearField(incidentstatus.FieldModifiedAt, field.TypeTime) + } + if value, ok := _u.mutation.DeletedAt(); ok { + _spec.SetField(incidentstatus.FieldDeletedAt, field.TypeTime, value) + } + if _u.mutation.DeletedAtCleared() { + _spec.ClearField(incidentstatus.FieldDeletedAt, field.TypeTime) + } + if value, ok := _u.mutation.CreatedBy(); ok { + _spec.SetField(incidentstatus.FieldCreatedBy, field.TypeString, value) + } + if _u.mutation.CreatedByCleared() { + _spec.ClearField(incidentstatus.FieldCreatedBy, field.TypeString) + } + if value, ok := _u.mutation.ModifiedBy(); ok { + _spec.SetField(incidentstatus.FieldModifiedBy, field.TypeString, value) + } + if _u.mutation.ModifiedByCleared() { + _spec.ClearField(incidentstatus.FieldModifiedBy, field.TypeString) + } + if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{incidentstatus.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + _u.mutation.done = true + return _node, nil +} + +// IncidentStatusUpdateOne is the builder for updating a single IncidentStatus entity. +type IncidentStatusUpdateOne struct { + config + fields []string + hooks []Hook + mutation *IncidentStatusMutation +} + +// SetIncidentID sets the "incident_id" field. +func (_u *IncidentStatusUpdateOne) SetIncidentID(v int) *IncidentStatusUpdateOne { + _u.mutation.ResetIncidentID() + _u.mutation.SetIncidentID(v) + return _u +} + +// SetNillableIncidentID sets the "incident_id" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableIncidentID(v *int) *IncidentStatusUpdateOne { + if v != nil { + _u.SetIncidentID(*v) + } + return _u +} + +// AddIncidentID adds value to the "incident_id" field. +func (_u *IncidentStatusUpdateOne) AddIncidentID(v int) *IncidentStatusUpdateOne { + _u.mutation.AddIncidentID(v) + return _u +} + +// ClearIncidentID clears the value of the "incident_id" field. +func (_u *IncidentStatusUpdateOne) ClearIncidentID() *IncidentStatusUpdateOne { + _u.mutation.ClearIncidentID() + return _u +} + +// SetTimestamp sets the "timestamp" field. +func (_u *IncidentStatusUpdateOne) SetTimestamp(v time.Time) *IncidentStatusUpdateOne { + _u.mutation.SetTimestamp(v) + return _u +} + +// SetNillableTimestamp sets the "timestamp" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableTimestamp(v *time.Time) *IncidentStatusUpdateOne { + if v != nil { + _u.SetTimestamp(*v) + } + return _u +} + +// SetText sets the "text" field. +func (_u *IncidentStatusUpdateOne) SetText(v string) *IncidentStatusUpdateOne { + _u.mutation.SetText(v) + return _u +} + +// SetNillableText sets the "text" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableText(v *string) *IncidentStatusUpdateOne { + if v != nil { + _u.SetText(*v) + } + return _u +} + +// SetStatus sets the "status" field. +func (_u *IncidentStatusUpdateOne) SetStatus(v string) *IncidentStatusUpdateOne { + _u.mutation.SetStatus(v) + return _u +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableStatus(v *string) *IncidentStatusUpdateOne { + if v != nil { + _u.SetStatus(*v) + } + return _u +} + +// SetCreatedAt sets the "created_at" field. +func (_u *IncidentStatusUpdateOne) SetCreatedAt(v time.Time) *IncidentStatusUpdateOne { + _u.mutation.SetCreatedAt(v) + return _u +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableCreatedAt(v *time.Time) *IncidentStatusUpdateOne { + if v != nil { + _u.SetCreatedAt(*v) + } + return _u +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (_u *IncidentStatusUpdateOne) ClearCreatedAt() *IncidentStatusUpdateOne { + _u.mutation.ClearCreatedAt() + return _u +} + +// SetModifiedAt sets the "modified_at" field. +func (_u *IncidentStatusUpdateOne) SetModifiedAt(v time.Time) *IncidentStatusUpdateOne { + _u.mutation.SetModifiedAt(v) + return _u +} + +// SetNillableModifiedAt sets the "modified_at" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableModifiedAt(v *time.Time) *IncidentStatusUpdateOne { + if v != nil { + _u.SetModifiedAt(*v) + } + return _u +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (_u *IncidentStatusUpdateOne) ClearModifiedAt() *IncidentStatusUpdateOne { + _u.mutation.ClearModifiedAt() + return _u +} + +// SetDeletedAt sets the "deleted_at" field. +func (_u *IncidentStatusUpdateOne) SetDeletedAt(v time.Time) *IncidentStatusUpdateOne { + _u.mutation.SetDeletedAt(v) + return _u +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableDeletedAt(v *time.Time) *IncidentStatusUpdateOne { + if v != nil { + _u.SetDeletedAt(*v) + } + return _u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (_u *IncidentStatusUpdateOne) ClearDeletedAt() *IncidentStatusUpdateOne { + _u.mutation.ClearDeletedAt() + return _u +} + +// SetCreatedBy sets the "created_by" field. +func (_u *IncidentStatusUpdateOne) SetCreatedBy(v string) *IncidentStatusUpdateOne { + _u.mutation.SetCreatedBy(v) + return _u +} + +// SetNillableCreatedBy sets the "created_by" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableCreatedBy(v *string) *IncidentStatusUpdateOne { + if v != nil { + _u.SetCreatedBy(*v) + } + return _u +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (_u *IncidentStatusUpdateOne) ClearCreatedBy() *IncidentStatusUpdateOne { + _u.mutation.ClearCreatedBy() + return _u +} + +// SetModifiedBy sets the "modified_by" field. +func (_u *IncidentStatusUpdateOne) SetModifiedBy(v string) *IncidentStatusUpdateOne { + _u.mutation.SetModifiedBy(v) + return _u +} + +// SetNillableModifiedBy sets the "modified_by" field if the given value is not nil. +func (_u *IncidentStatusUpdateOne) SetNillableModifiedBy(v *string) *IncidentStatusUpdateOne { + if v != nil { + _u.SetModifiedBy(*v) + } + return _u +} + +// ClearModifiedBy clears the value of the "modified_by" field. +func (_u *IncidentStatusUpdateOne) ClearModifiedBy() *IncidentStatusUpdateOne { + _u.mutation.ClearModifiedBy() + return _u +} + +// Mutation returns the IncidentStatusMutation object of the builder. +func (_u *IncidentStatusUpdateOne) Mutation() *IncidentStatusMutation { + return _u.mutation +} + +// Where appends a list predicates to the IncidentStatusUpdate builder. +func (_u *IncidentStatusUpdateOne) Where(ps ...predicate.IncidentStatus) *IncidentStatusUpdateOne { + _u.mutation.Where(ps...) + return _u +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (_u *IncidentStatusUpdateOne) Select(field string, fields ...string) *IncidentStatusUpdateOne { + _u.fields = append([]string{field}, fields...) + return _u +} + +// Save executes the query and returns the updated IncidentStatus entity. +func (_u *IncidentStatusUpdateOne) Save(ctx context.Context) (*IncidentStatus, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *IncidentStatusUpdateOne) SaveX(ctx context.Context) *IncidentStatus { + node, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (_u *IncidentStatusUpdateOne) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *IncidentStatusUpdateOne) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *IncidentStatusUpdateOne) check() error { + if v, ok := _u.mutation.Text(); ok { + if err := incidentstatus.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "IncidentStatus.text": %w`, err)} + } + } + if v, ok := _u.mutation.Status(); ok { + if err := incidentstatus.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "IncidentStatus.status": %w`, err)} + } + } + return nil +} + +func (_u *IncidentStatusUpdateOne) sqlSave(ctx context.Context) (_node *IncidentStatus, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(incidentstatus.Table, incidentstatus.Columns, sqlgraph.NewFieldSpec(incidentstatus.FieldID, field.TypeInt)) + id, ok := _u.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "IncidentStatus.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := _u.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, incidentstatus.FieldID) + for _, f := range fields { + if !incidentstatus.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != incidentstatus.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.IncidentID(); ok { + _spec.SetField(incidentstatus.FieldIncidentID, field.TypeInt, value) + } + if value, ok := _u.mutation.AddedIncidentID(); ok { + _spec.AddField(incidentstatus.FieldIncidentID, field.TypeInt, value) + } + if _u.mutation.IncidentIDCleared() { + _spec.ClearField(incidentstatus.FieldIncidentID, field.TypeInt) + } + if value, ok := _u.mutation.Timestamp(); ok { + _spec.SetField(incidentstatus.FieldTimestamp, field.TypeTime, value) + } + if value, ok := _u.mutation.Text(); ok { + _spec.SetField(incidentstatus.FieldText, field.TypeString, value) + } + if value, ok := _u.mutation.Status(); ok { + _spec.SetField(incidentstatus.FieldStatus, field.TypeString, value) + } + if value, ok := _u.mutation.CreatedAt(); ok { + _spec.SetField(incidentstatus.FieldCreatedAt, field.TypeTime, value) + } + if _u.mutation.CreatedAtCleared() { + _spec.ClearField(incidentstatus.FieldCreatedAt, field.TypeTime) + } + if value, ok := _u.mutation.ModifiedAt(); ok { + _spec.SetField(incidentstatus.FieldModifiedAt, field.TypeTime, value) + } + if _u.mutation.ModifiedAtCleared() { + _spec.ClearField(incidentstatus.FieldModifiedAt, field.TypeTime) + } + if value, ok := _u.mutation.DeletedAt(); ok { + _spec.SetField(incidentstatus.FieldDeletedAt, field.TypeTime, value) + } + if _u.mutation.DeletedAtCleared() { + _spec.ClearField(incidentstatus.FieldDeletedAt, field.TypeTime) + } + if value, ok := _u.mutation.CreatedBy(); ok { + _spec.SetField(incidentstatus.FieldCreatedBy, field.TypeString, value) + } + if _u.mutation.CreatedByCleared() { + _spec.ClearField(incidentstatus.FieldCreatedBy, field.TypeString) + } + if value, ok := _u.mutation.ModifiedBy(); ok { + _spec.SetField(incidentstatus.FieldModifiedBy, field.TypeString, value) + } + if _u.mutation.ModifiedByCleared() { + _spec.ClearField(incidentstatus.FieldModifiedBy, field.TypeString) + } + _node = &IncidentStatus{config: _u.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{incidentstatus.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + _u.mutation.done = true + return _node, nil +} diff --git a/ent/migrate/migrate.go b/ent/migrate/migrate.go new file mode 100644 index 0000000..d8d3bcb --- /dev/null +++ b/ent/migrate/migrate.go @@ -0,0 +1,96 @@ +// Code generated by ent, DO NOT EDIT. + +package migrate + +import ( + "context" + "fmt" + "io" + + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/sql/schema" +) + +var ( + // WithGlobalUniqueID sets the universal ids options to the migration. + // If this option is enabled, ent migration will allocate a 1<<32 range + // for the ids of each entity (table). + // Note that this option cannot be applied on tables that already exist. + WithGlobalUniqueID = schema.WithGlobalUniqueID + // WithDropColumn sets the drop column option to the migration. + // If this option is enabled, ent migration will drop old columns + // that were used for both fields and edges. This defaults to false. + WithDropColumn = schema.WithDropColumn + // WithDropIndex sets the drop index option to the migration. + // If this option is enabled, ent migration will drop old indexes + // that were defined in the schema. This defaults to false. + // Note that unique constraints are defined using `UNIQUE INDEX`, + // and therefore, it's recommended to enable this option to get more + // flexibility in the schema changes. + WithDropIndex = schema.WithDropIndex + // WithForeignKeys enables creating foreign-key in schema DDL. This defaults to true. + WithForeignKeys = schema.WithForeignKeys +) + +// Schema is the API for creating, migrating and dropping a schema. +type Schema struct { + drv dialect.Driver +} + +// NewSchema creates a new schema client. +func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} } + +// Create creates all schema resources. +func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error { + return Create(ctx, s, Tables, opts...) +} + +// Create creates all table resources using the given schema driver. +func Create(ctx context.Context, s *Schema, tables []*schema.Table, opts ...schema.MigrateOption) error { + migrate, err := schema.NewMigrate(s.drv, opts...) + if err != nil { + return fmt.Errorf("ent/migrate: %w", err) + } + return migrate.Create(ctx, tables...) +} + +// Diff compares the state read from a database connection or migration directory with +// the state defined by the Ent schema. Changes will be written to new migration files. +func Diff(ctx context.Context, url string, opts ...schema.MigrateOption) error { + return NamedDiff(ctx, url, "changes", opts...) +} + +// NamedDiff compares the state read from a database connection or migration directory with +// the state defined by the Ent schema. Changes will be written to new named migration files. +func NamedDiff(ctx context.Context, url, name string, opts ...schema.MigrateOption) error { + return schema.Diff(ctx, url, name, Tables, opts...) +} + +// Diff creates a migration file containing the statements to resolve the diff +// between the Ent schema and the connected database. +func (s *Schema) Diff(ctx context.Context, opts ...schema.MigrateOption) error { + migrate, err := schema.NewMigrate(s.drv, opts...) + if err != nil { + return fmt.Errorf("ent/migrate: %w", err) + } + return migrate.Diff(ctx, Tables...) +} + +// NamedDiff creates a named migration file containing the statements to resolve the diff +// between the Ent schema and the connected database. +func (s *Schema) NamedDiff(ctx context.Context, name string, opts ...schema.MigrateOption) error { + migrate, err := schema.NewMigrate(s.drv, opts...) + if err != nil { + return fmt.Errorf("ent/migrate: %w", err) + } + return migrate.NamedDiff(ctx, name, Tables...) +} + +// WriteTo writes the schema changes to w instead of running them against the database. +// +// if err := client.Schema.WriteTo(context.Background(), os.Stdout); err != nil { +// log.Fatal(err) +// } +func (s *Schema) WriteTo(ctx context.Context, w io.Writer, opts ...schema.MigrateOption) error { + return Create(ctx, &Schema{drv: &schema.WriteDriver{Writer: w, Driver: s.drv}}, Tables, opts...) +} diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go new file mode 100644 index 0000000..2a007d1 --- /dev/null +++ b/ent/migrate/schema.go @@ -0,0 +1,257 @@ +// Code generated by ent, DO NOT EDIT. + +package migrate + +import ( + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/dialect/sql/schema" + "entgo.io/ent/schema/field" +) + +var ( + // ComponentColumns holds the columns for the "component" table. + ComponentColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true, SchemaType: map[string]string{"postgres": "serial"}}, + {Name: "name", Type: field.TypeString}, + {Name: "created_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "modified_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + } + // ComponentTable holds the schema information for the "component" table. + ComponentTable = &schema.Table{ + Name: "component", + Columns: ComponentColumns, + PrimaryKey: []*schema.Column{ComponentColumns[0]}, + Indexes: []*schema.Index{ + { + Name: "ix_component_id", + Unique: false, + Columns: []*schema.Column{ComponentColumns[0]}, + }, + }, + } + // ComponentAttributeColumns holds the columns for the "component_attribute" table. + ComponentAttributeColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true, SchemaType: map[string]string{"postgres": "serial"}}, + {Name: "name", Type: field.TypeString}, + {Name: "value", Type: field.TypeString}, + {Name: "component_id", Type: field.TypeInt, Nullable: true, SchemaType: map[string]string{"postgres": "serial"}}, + } + // ComponentAttributeTable holds the schema information for the "component_attribute" table. + ComponentAttributeTable = &schema.Table{ + Name: "component_attribute", + Columns: ComponentAttributeColumns, + PrimaryKey: []*schema.Column{ComponentAttributeColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "component_attribute_component_id_fkey", + Columns: []*schema.Column{ComponentAttributeColumns[3]}, + RefColumns: []*schema.Column{ComponentColumns[0]}, + OnDelete: schema.NoAction, + }, + }, + Indexes: []*schema.Index{ + { + Name: "ix_component_attribute_id", + Unique: false, + Columns: []*schema.Column{ComponentAttributeColumns[0]}, + }, + { + Name: "ix_component_attribute_component_id", + Unique: false, + Columns: []*schema.Column{ComponentAttributeColumns[3]}, + }, + { + Name: "unique_component_attribute", + Unique: true, + Columns: []*schema.Column{ComponentAttributeColumns[3], ComponentAttributeColumns[1]}, + }, + }, + } + // IncidentColumns holds the columns for the "incident" table. + IncidentColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true, SchemaType: map[string]string{"postgres": "serial"}}, + {Name: "text", Type: field.TypeString}, + {Name: "description", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "varchar(1500)"}}, + {Name: "start_date", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "end_date", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "impact", Type: field.TypeInt, SchemaType: map[string]string{"postgres": "smallint"}}, + {Name: "system", Type: field.TypeBool, Default: false}, + {Name: "type", Type: field.TypeEnum, Enums: []string{"incident", "info", "maintenance"}, SchemaType: map[string]string{"postgres": "varchar"}}, + {Name: "status", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "varchar(50)"}}, + {Name: "created_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "modified_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "created_by", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "varchar(255)"}}, + {Name: "contact_email", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "varchar(255)"}}, + {Name: "version", Type: field.TypeInt, Default: 1, SchemaType: map[string]string{"postgres": "integer"}}, + } + // IncidentTable holds the schema information for the "incident" table. + IncidentTable = &schema.Table{ + Name: "incident", + Columns: IncidentColumns, + PrimaryKey: []*schema.Column{IncidentColumns[0]}, + Indexes: []*schema.Index{ + { + Name: "ix_incident_id", + Unique: false, + Columns: []*schema.Column{IncidentColumns[0]}, + }, + }, + } + // IncidentStatusColumns holds the columns for the "incident_status" table. + IncidentStatusColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true, SchemaType: map[string]string{"postgres": "serial"}}, + {Name: "incident_id", Type: field.TypeInt, Nullable: true, SchemaType: map[string]string{"postgres": "integer"}}, + {Name: "timestamp", Type: field.TypeTime, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "text", Type: field.TypeString}, + {Name: "status", Type: field.TypeString}, + {Name: "created_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "modified_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamp"}}, + {Name: "created_by", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "varchar(255)"}}, + {Name: "modified_by", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "varchar(255)"}}, + } + // IncidentStatusTable holds the schema information for the "incident_status" table. + IncidentStatusTable = &schema.Table{ + Name: "incident_status", + Columns: IncidentStatusColumns, + PrimaryKey: []*schema.Column{IncidentStatusColumns[0]}, + Indexes: []*schema.Index{ + { + Name: "ix_incident_status_id", + Unique: false, + Columns: []*schema.Column{IncidentStatusColumns[0]}, + }, + { + Name: "ix_incident_status_incident_id", + Unique: false, + Columns: []*schema.Column{IncidentStatusColumns[1]}, + }, + { + Name: "idx_incident_status_incident_id_timestamp", + Unique: false, + Columns: []*schema.Column{IncidentStatusColumns[1], IncidentStatusColumns[2]}, + }, + }, + } + // NotificationOutboxColumns holds the columns for the "notification_outbox" table. + NotificationOutboxColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true, SchemaType: map[string]string{"postgres": "serial"}}, + {Name: "kind", Type: field.TypeString, SchemaType: map[string]string{"postgres": "varchar(64)"}}, + {Name: "recipient", Type: field.TypeString, SchemaType: map[string]string{"postgres": "varchar(255)"}}, + {Name: "payload", Type: field.TypeJSON, SchemaType: map[string]string{"postgres": "jsonb"}}, + {Name: "change_id", Type: field.TypeString, SchemaType: map[string]string{"postgres": "uuid"}}, + {Name: "dedup_key", Type: field.TypeString, SchemaType: map[string]string{"postgres": "varchar(255)"}}, + {Name: "status", Type: field.TypeString, Default: "pending", SchemaType: map[string]string{"postgres": "varchar(20)"}}, + {Name: "attempts", Type: field.TypeInt, Default: 0, SchemaType: map[string]string{"postgres": "integer"}}, + {Name: "next_attempt_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}}, + {Name: "locked_by", Type: field.TypeString, Nullable: true, SchemaType: map[string]string{"postgres": "varchar(255)"}}, + {Name: "locked_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"postgres": "timestamptz"}}, + {Name: "last_error", Type: field.TypeString, Nullable: true, Size: 2147483647}, + {Name: "created_at", Type: field.TypeTime, Default: schema.Expr("NOW()"), SchemaType: map[string]string{"postgres": "timestamptz"}}, + {Name: "updated_at", Type: field.TypeTime, Default: schema.Expr("NOW()"), SchemaType: map[string]string{"postgres": "timestamptz"}}, + {Name: "incident_id", Type: field.TypeInt, SchemaType: map[string]string{"postgres": "serial"}}, + } + // NotificationOutboxTable holds the schema information for the "notification_outbox" table. + NotificationOutboxTable = &schema.Table{ + Name: "notification_outbox", + Columns: NotificationOutboxColumns, + PrimaryKey: []*schema.Column{NotificationOutboxColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "notification_outbox_incident_id_fkey", + Columns: []*schema.Column{NotificationOutboxColumns[14]}, + RefColumns: []*schema.Column{IncidentColumns[0]}, + OnDelete: schema.NoAction, + }, + }, + Indexes: []*schema.Index{ + { + Name: "idx_outbox_dedup", + Unique: true, + Columns: []*schema.Column{NotificationOutboxColumns[5]}, + }, + { + Name: "idx_outbox_dispatch", + Unique: false, + Columns: []*schema.Column{NotificationOutboxColumns[8]}, + Annotation: &entsql.IndexAnnotation{ + Where: "status = 'pending'", + }, + }, + { + Name: "idx_outbox_stale_processing", + Unique: false, + Columns: []*schema.Column{NotificationOutboxColumns[10]}, + Annotation: &entsql.IndexAnnotation{ + Where: "status = 'processing'", + }, + }, + { + Name: "idx_outbox_retention", + Unique: false, + Columns: []*schema.Column{NotificationOutboxColumns[13]}, + Annotation: &entsql.IndexAnnotation{ + Where: "status = 'sent'", + }, + }, + }, + } + // IncidentComponentRelationColumns holds the columns for the "incident_component_relation" table. + IncidentComponentRelationColumns = []*schema.Column{ + {Name: "incident_id", Type: field.TypeInt, SchemaType: map[string]string{"postgres": "serial"}}, + {Name: "component_id", Type: field.TypeInt, SchemaType: map[string]string{"postgres": "serial"}}, + } + // IncidentComponentRelationTable holds the schema information for the "incident_component_relation" table. + IncidentComponentRelationTable = &schema.Table{ + Name: "incident_component_relation", + Columns: IncidentComponentRelationColumns, + PrimaryKey: []*schema.Column{IncidentComponentRelationColumns[0], IncidentComponentRelationColumns[1]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "incident_component_relation_incident_id_fkey", + Columns: []*schema.Column{IncidentComponentRelationColumns[0]}, + RefColumns: []*schema.Column{IncidentColumns[0]}, + OnDelete: schema.Cascade, + }, + { + Symbol: "incident_component_relation_component_id_fkey", + Columns: []*schema.Column{IncidentComponentRelationColumns[1]}, + RefColumns: []*schema.Column{ComponentColumns[0]}, + OnDelete: schema.Cascade, + }, + }, + } + // Tables holds all the tables in the schema. + Tables = []*schema.Table{ + ComponentTable, + ComponentAttributeTable, + IncidentTable, + IncidentStatusTable, + NotificationOutboxTable, + IncidentComponentRelationTable, + } +) + +func init() { + ComponentTable.Annotation = &entsql.Annotation{ + Table: "component", + } + ComponentAttributeTable.ForeignKeys[0].RefTable = ComponentTable + ComponentAttributeTable.Annotation = &entsql.Annotation{ + Table: "component_attribute", + } + IncidentTable.Annotation = &entsql.Annotation{ + Table: "incident", + } + IncidentStatusTable.Annotation = &entsql.Annotation{ + Table: "incident_status", + } + NotificationOutboxTable.ForeignKeys[0].RefTable = IncidentTable + NotificationOutboxTable.Annotation = &entsql.Annotation{ + Table: "notification_outbox", + } + IncidentComponentRelationTable.ForeignKeys[0].RefTable = IncidentTable + IncidentComponentRelationTable.ForeignKeys[1].RefTable = ComponentTable +} diff --git a/ent/mutation.go b/ent/mutation.go new file mode 100644 index 0000000..68ee753 --- /dev/null +++ b/ent/mutation.go @@ -0,0 +1,4840 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "sync" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +const ( + // Operation types. + OpCreate = ent.OpCreate + OpDelete = ent.OpDelete + OpDeleteOne = ent.OpDeleteOne + OpUpdate = ent.OpUpdate + OpUpdateOne = ent.OpUpdateOne + + // Node types. + TypeComponent = "Component" + TypeComponentAttr = "ComponentAttr" + TypeIncident = "Incident" + TypeIncidentStatus = "IncidentStatus" + TypeNotificationOutbox = "NotificationOutbox" +) + +// ComponentMutation represents an operation that mutates the Component nodes in the graph. +type ComponentMutation struct { + config + op Op + typ string + id *int + name *string + created_at *time.Time + modified_at *time.Time + deleted_at *time.Time + clearedFields map[string]struct{} + attributes map[int]struct{} + removedattributes map[int]struct{} + clearedattributes bool + incidents map[int]struct{} + removedincidents map[int]struct{} + clearedincidents bool + done bool + oldValue func(context.Context) (*Component, error) + predicates []predicate.Component +} + +var _ ent.Mutation = (*ComponentMutation)(nil) + +// componentOption allows management of the mutation configuration using functional options. +type componentOption func(*ComponentMutation) + +// newComponentMutation creates new mutation for the Component entity. +func newComponentMutation(c config, op Op, opts ...componentOption) *ComponentMutation { + m := &ComponentMutation{ + config: c, + op: op, + typ: TypeComponent, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withComponentID sets the ID field of the mutation. +func withComponentID(id int) componentOption { + return func(m *ComponentMutation) { + var ( + err error + once sync.Once + value *Component + ) + m.oldValue = func(ctx context.Context) (*Component, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Component.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withComponent sets the old Component of the mutation. +func withComponent(node *Component) componentOption { + return func(m *ComponentMutation) { + m.oldValue = func(context.Context) (*Component, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m ComponentMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m ComponentMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of Component entities. +func (m *ComponentMutation) SetID(id int) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *ComponentMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *ComponentMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Component.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetName sets the "name" field. +func (m *ComponentMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *ComponentMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the Component entity. +// If the Component 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 *ComponentMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *ComponentMutation) ResetName() { + m.name = nil +} + +// SetCreatedAt sets the "created_at" field. +func (m *ComponentMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *ComponentMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the Component entity. +// If the Component 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 *ComponentMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (m *ComponentMutation) ClearCreatedAt() { + m.created_at = nil + m.clearedFields[component.FieldCreatedAt] = struct{}{} +} + +// CreatedAtCleared returns if the "created_at" field was cleared in this mutation. +func (m *ComponentMutation) CreatedAtCleared() bool { + _, ok := m.clearedFields[component.FieldCreatedAt] + return ok +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *ComponentMutation) ResetCreatedAt() { + m.created_at = nil + delete(m.clearedFields, component.FieldCreatedAt) +} + +// SetModifiedAt sets the "modified_at" field. +func (m *ComponentMutation) SetModifiedAt(t time.Time) { + m.modified_at = &t +} + +// ModifiedAt returns the value of the "modified_at" field in the mutation. +func (m *ComponentMutation) ModifiedAt() (r time.Time, exists bool) { + v := m.modified_at + if v == nil { + return + } + return *v, true +} + +// OldModifiedAt returns the old "modified_at" field's value of the Component entity. +// If the Component 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 *ComponentMutation) OldModifiedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldModifiedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldModifiedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldModifiedAt: %w", err) + } + return oldValue.ModifiedAt, nil +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (m *ComponentMutation) ClearModifiedAt() { + m.modified_at = nil + m.clearedFields[component.FieldModifiedAt] = struct{}{} +} + +// ModifiedAtCleared returns if the "modified_at" field was cleared in this mutation. +func (m *ComponentMutation) ModifiedAtCleared() bool { + _, ok := m.clearedFields[component.FieldModifiedAt] + return ok +} + +// ResetModifiedAt resets all changes to the "modified_at" field. +func (m *ComponentMutation) ResetModifiedAt() { + m.modified_at = nil + delete(m.clearedFields, component.FieldModifiedAt) +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *ComponentMutation) SetDeletedAt(t time.Time) { + m.deleted_at = &t +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *ComponentMutation) DeletedAt() (r time.Time, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the Component entity. +// If the Component 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 *ComponentMutation) OldDeletedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *ComponentMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[component.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *ComponentMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[component.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *ComponentMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, component.FieldDeletedAt) +} + +// AddAttributeIDs adds the "attributes" edge to the ComponentAttr entity by ids. +func (m *ComponentMutation) AddAttributeIDs(ids ...int) { + if m.attributes == nil { + m.attributes = make(map[int]struct{}) + } + for i := range ids { + m.attributes[ids[i]] = struct{}{} + } +} + +// ClearAttributes clears the "attributes" edge to the ComponentAttr entity. +func (m *ComponentMutation) ClearAttributes() { + m.clearedattributes = true +} + +// AttributesCleared reports if the "attributes" edge to the ComponentAttr entity was cleared. +func (m *ComponentMutation) AttributesCleared() bool { + return m.clearedattributes +} + +// RemoveAttributeIDs removes the "attributes" edge to the ComponentAttr entity by IDs. +func (m *ComponentMutation) RemoveAttributeIDs(ids ...int) { + if m.removedattributes == nil { + m.removedattributes = make(map[int]struct{}) + } + for i := range ids { + delete(m.attributes, ids[i]) + m.removedattributes[ids[i]] = struct{}{} + } +} + +// RemovedAttributes returns the removed IDs of the "attributes" edge to the ComponentAttr entity. +func (m *ComponentMutation) RemovedAttributesIDs() (ids []int) { + for id := range m.removedattributes { + ids = append(ids, id) + } + return +} + +// AttributesIDs returns the "attributes" edge IDs in the mutation. +func (m *ComponentMutation) AttributesIDs() (ids []int) { + for id := range m.attributes { + ids = append(ids, id) + } + return +} + +// ResetAttributes resets all changes to the "attributes" edge. +func (m *ComponentMutation) ResetAttributes() { + m.attributes = nil + m.clearedattributes = false + m.removedattributes = nil +} + +// AddIncidentIDs adds the "incidents" edge to the Incident entity by ids. +func (m *ComponentMutation) AddIncidentIDs(ids ...int) { + if m.incidents == nil { + m.incidents = make(map[int]struct{}) + } + for i := range ids { + m.incidents[ids[i]] = struct{}{} + } +} + +// ClearIncidents clears the "incidents" edge to the Incident entity. +func (m *ComponentMutation) ClearIncidents() { + m.clearedincidents = true +} + +// IncidentsCleared reports if the "incidents" edge to the Incident entity was cleared. +func (m *ComponentMutation) IncidentsCleared() bool { + return m.clearedincidents +} + +// RemoveIncidentIDs removes the "incidents" edge to the Incident entity by IDs. +func (m *ComponentMutation) RemoveIncidentIDs(ids ...int) { + if m.removedincidents == nil { + m.removedincidents = make(map[int]struct{}) + } + for i := range ids { + delete(m.incidents, ids[i]) + m.removedincidents[ids[i]] = struct{}{} + } +} + +// RemovedIncidents returns the removed IDs of the "incidents" edge to the Incident entity. +func (m *ComponentMutation) RemovedIncidentsIDs() (ids []int) { + for id := range m.removedincidents { + ids = append(ids, id) + } + return +} + +// IncidentsIDs returns the "incidents" edge IDs in the mutation. +func (m *ComponentMutation) IncidentsIDs() (ids []int) { + for id := range m.incidents { + ids = append(ids, id) + } + return +} + +// ResetIncidents resets all changes to the "incidents" edge. +func (m *ComponentMutation) ResetIncidents() { + m.incidents = nil + m.clearedincidents = false + m.removedincidents = nil +} + +// Where appends a list predicates to the ComponentMutation builder. +func (m *ComponentMutation) Where(ps ...predicate.Component) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the ComponentMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *ComponentMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.Component, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *ComponentMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *ComponentMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (Component). +func (m *ComponentMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *ComponentMutation) Fields() []string { + fields := make([]string, 0, 4) + if m.name != nil { + fields = append(fields, component.FieldName) + } + if m.created_at != nil { + fields = append(fields, component.FieldCreatedAt) + } + if m.modified_at != nil { + fields = append(fields, component.FieldModifiedAt) + } + if m.deleted_at != nil { + fields = append(fields, component.FieldDeletedAt) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *ComponentMutation) Field(name string) (ent.Value, bool) { + switch name { + case component.FieldName: + return m.Name() + case component.FieldCreatedAt: + return m.CreatedAt() + case component.FieldModifiedAt: + return m.ModifiedAt() + case component.FieldDeletedAt: + return m.DeletedAt() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *ComponentMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case component.FieldName: + return m.OldName(ctx) + case component.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case component.FieldModifiedAt: + return m.OldModifiedAt(ctx) + case component.FieldDeletedAt: + return m.OldDeletedAt(ctx) + } + return nil, fmt.Errorf("unknown Component field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ComponentMutation) SetField(name string, value ent.Value) error { + switch name { + case component.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case component.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case component.FieldModifiedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetModifiedAt(v) + return nil + case component.FieldDeletedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + } + return fmt.Errorf("unknown Component field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *ComponentMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *ComponentMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ComponentMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown Component numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *ComponentMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(component.FieldCreatedAt) { + fields = append(fields, component.FieldCreatedAt) + } + if m.FieldCleared(component.FieldModifiedAt) { + fields = append(fields, component.FieldModifiedAt) + } + if m.FieldCleared(component.FieldDeletedAt) { + fields = append(fields, component.FieldDeletedAt) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *ComponentMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *ComponentMutation) ClearField(name string) error { + switch name { + case component.FieldCreatedAt: + m.ClearCreatedAt() + return nil + case component.FieldModifiedAt: + m.ClearModifiedAt() + return nil + case component.FieldDeletedAt: + m.ClearDeletedAt() + return nil + } + return fmt.Errorf("unknown Component nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *ComponentMutation) ResetField(name string) error { + switch name { + case component.FieldName: + m.ResetName() + return nil + case component.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case component.FieldModifiedAt: + m.ResetModifiedAt() + return nil + case component.FieldDeletedAt: + m.ResetDeletedAt() + return nil + } + return fmt.Errorf("unknown Component field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *ComponentMutation) AddedEdges() []string { + edges := make([]string, 0, 2) + if m.attributes != nil { + edges = append(edges, component.EdgeAttributes) + } + if m.incidents != nil { + edges = append(edges, component.EdgeIncidents) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *ComponentMutation) AddedIDs(name string) []ent.Value { + switch name { + case component.EdgeAttributes: + ids := make([]ent.Value, 0, len(m.attributes)) + for id := range m.attributes { + ids = append(ids, id) + } + return ids + case component.EdgeIncidents: + ids := make([]ent.Value, 0, len(m.incidents)) + for id := range m.incidents { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *ComponentMutation) RemovedEdges() []string { + edges := make([]string, 0, 2) + if m.removedattributes != nil { + edges = append(edges, component.EdgeAttributes) + } + if m.removedincidents != nil { + edges = append(edges, component.EdgeIncidents) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *ComponentMutation) RemovedIDs(name string) []ent.Value { + switch name { + case component.EdgeAttributes: + ids := make([]ent.Value, 0, len(m.removedattributes)) + for id := range m.removedattributes { + ids = append(ids, id) + } + return ids + case component.EdgeIncidents: + ids := make([]ent.Value, 0, len(m.removedincidents)) + for id := range m.removedincidents { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *ComponentMutation) ClearedEdges() []string { + edges := make([]string, 0, 2) + if m.clearedattributes { + edges = append(edges, component.EdgeAttributes) + } + if m.clearedincidents { + edges = append(edges, component.EdgeIncidents) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *ComponentMutation) EdgeCleared(name string) bool { + switch name { + case component.EdgeAttributes: + return m.clearedattributes + case component.EdgeIncidents: + return m.clearedincidents + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *ComponentMutation) ClearEdge(name string) error { + switch name { + } + return fmt.Errorf("unknown Component unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *ComponentMutation) ResetEdge(name string) error { + switch name { + case component.EdgeAttributes: + m.ResetAttributes() + return nil + case component.EdgeIncidents: + m.ResetIncidents() + return nil + } + return fmt.Errorf("unknown Component edge %s", name) +} + +// ComponentAttrMutation represents an operation that mutates the ComponentAttr nodes in the graph. +type ComponentAttrMutation struct { + config + op Op + typ string + id *int + name *string + value *string + clearedFields map[string]struct{} + component *int + clearedcomponent bool + done bool + oldValue func(context.Context) (*ComponentAttr, error) + predicates []predicate.ComponentAttr +} + +var _ ent.Mutation = (*ComponentAttrMutation)(nil) + +// componentattrOption allows management of the mutation configuration using functional options. +type componentattrOption func(*ComponentAttrMutation) + +// newComponentAttrMutation creates new mutation for the ComponentAttr entity. +func newComponentAttrMutation(c config, op Op, opts ...componentattrOption) *ComponentAttrMutation { + m := &ComponentAttrMutation{ + config: c, + op: op, + typ: TypeComponentAttr, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withComponentAttrID sets the ID field of the mutation. +func withComponentAttrID(id int) componentattrOption { + return func(m *ComponentAttrMutation) { + var ( + err error + once sync.Once + value *ComponentAttr + ) + m.oldValue = func(ctx context.Context) (*ComponentAttr, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().ComponentAttr.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withComponentAttr sets the old ComponentAttr of the mutation. +func withComponentAttr(node *ComponentAttr) componentattrOption { + return func(m *ComponentAttrMutation) { + m.oldValue = func(context.Context) (*ComponentAttr, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m ComponentAttrMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m ComponentAttrMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of ComponentAttr entities. +func (m *ComponentAttrMutation) SetID(id int) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *ComponentAttrMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *ComponentAttrMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().ComponentAttr.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetComponentID sets the "component_id" field. +func (m *ComponentAttrMutation) SetComponentID(i int) { + m.component = &i +} + +// ComponentID returns the value of the "component_id" field in the mutation. +func (m *ComponentAttrMutation) ComponentID() (r int, exists bool) { + v := m.component + if v == nil { + return + } + return *v, true +} + +// OldComponentID returns the old "component_id" field's value of the ComponentAttr entity. +// If the ComponentAttr 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 *ComponentAttrMutation) OldComponentID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldComponentID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldComponentID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldComponentID: %w", err) + } + return oldValue.ComponentID, nil +} + +// ClearComponentID clears the value of the "component_id" field. +func (m *ComponentAttrMutation) ClearComponentID() { + m.component = nil + m.clearedFields[componentattr.FieldComponentID] = struct{}{} +} + +// ComponentIDCleared returns if the "component_id" field was cleared in this mutation. +func (m *ComponentAttrMutation) ComponentIDCleared() bool { + _, ok := m.clearedFields[componentattr.FieldComponentID] + return ok +} + +// ResetComponentID resets all changes to the "component_id" field. +func (m *ComponentAttrMutation) ResetComponentID() { + m.component = nil + delete(m.clearedFields, componentattr.FieldComponentID) +} + +// SetName sets the "name" field. +func (m *ComponentAttrMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *ComponentAttrMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the ComponentAttr entity. +// If the ComponentAttr 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 *ComponentAttrMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *ComponentAttrMutation) ResetName() { + m.name = nil +} + +// SetValue sets the "value" field. +func (m *ComponentAttrMutation) SetValue(s string) { + m.value = &s +} + +// Value returns the value of the "value" field in the mutation. +func (m *ComponentAttrMutation) Value() (r string, exists bool) { + v := m.value + if v == nil { + return + } + return *v, true +} + +// OldValue returns the old "value" field's value of the ComponentAttr entity. +// If the ComponentAttr 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 *ComponentAttrMutation) OldValue(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldValue is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldValue requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldValue: %w", err) + } + return oldValue.Value, nil +} + +// ResetValue resets all changes to the "value" field. +func (m *ComponentAttrMutation) ResetValue() { + m.value = nil +} + +// ClearComponent clears the "component" edge to the Component entity. +func (m *ComponentAttrMutation) ClearComponent() { + m.clearedcomponent = true + m.clearedFields[componentattr.FieldComponentID] = struct{}{} +} + +// ComponentCleared reports if the "component" edge to the Component entity was cleared. +func (m *ComponentAttrMutation) ComponentCleared() bool { + return m.ComponentIDCleared() || m.clearedcomponent +} + +// ComponentIDs returns the "component" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// ComponentID instead. It exists only for internal usage by the builders. +func (m *ComponentAttrMutation) ComponentIDs() (ids []int) { + if id := m.component; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetComponent resets all changes to the "component" edge. +func (m *ComponentAttrMutation) ResetComponent() { + m.component = nil + m.clearedcomponent = false +} + +// Where appends a list predicates to the ComponentAttrMutation builder. +func (m *ComponentAttrMutation) Where(ps ...predicate.ComponentAttr) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the ComponentAttrMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *ComponentAttrMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.ComponentAttr, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *ComponentAttrMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *ComponentAttrMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (ComponentAttr). +func (m *ComponentAttrMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *ComponentAttrMutation) Fields() []string { + fields := make([]string, 0, 3) + if m.component != nil { + fields = append(fields, componentattr.FieldComponentID) + } + if m.name != nil { + fields = append(fields, componentattr.FieldName) + } + if m.value != nil { + fields = append(fields, componentattr.FieldValue) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *ComponentAttrMutation) Field(name string) (ent.Value, bool) { + switch name { + case componentattr.FieldComponentID: + return m.ComponentID() + case componentattr.FieldName: + return m.Name() + case componentattr.FieldValue: + return m.Value() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *ComponentAttrMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case componentattr.FieldComponentID: + return m.OldComponentID(ctx) + case componentattr.FieldName: + return m.OldName(ctx) + case componentattr.FieldValue: + return m.OldValue(ctx) + } + return nil, fmt.Errorf("unknown ComponentAttr field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ComponentAttrMutation) SetField(name string, value ent.Value) error { + switch name { + case componentattr.FieldComponentID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetComponentID(v) + return nil + case componentattr.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case componentattr.FieldValue: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetValue(v) + return nil + } + return fmt.Errorf("unknown ComponentAttr field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *ComponentAttrMutation) AddedFields() []string { + var fields []string + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *ComponentAttrMutation) AddedField(name string) (ent.Value, bool) { + switch name { + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ComponentAttrMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown ComponentAttr numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *ComponentAttrMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(componentattr.FieldComponentID) { + fields = append(fields, componentattr.FieldComponentID) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *ComponentAttrMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *ComponentAttrMutation) ClearField(name string) error { + switch name { + case componentattr.FieldComponentID: + m.ClearComponentID() + return nil + } + return fmt.Errorf("unknown ComponentAttr nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *ComponentAttrMutation) ResetField(name string) error { + switch name { + case componentattr.FieldComponentID: + m.ResetComponentID() + return nil + case componentattr.FieldName: + m.ResetName() + return nil + case componentattr.FieldValue: + m.ResetValue() + return nil + } + return fmt.Errorf("unknown ComponentAttr field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *ComponentAttrMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.component != nil { + edges = append(edges, componentattr.EdgeComponent) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *ComponentAttrMutation) AddedIDs(name string) []ent.Value { + switch name { + case componentattr.EdgeComponent: + if id := m.component; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *ComponentAttrMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *ComponentAttrMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *ComponentAttrMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedcomponent { + edges = append(edges, componentattr.EdgeComponent) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *ComponentAttrMutation) EdgeCleared(name string) bool { + switch name { + case componentattr.EdgeComponent: + return m.clearedcomponent + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *ComponentAttrMutation) ClearEdge(name string) error { + switch name { + case componentattr.EdgeComponent: + m.ClearComponent() + return nil + } + return fmt.Errorf("unknown ComponentAttr unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *ComponentAttrMutation) ResetEdge(name string) error { + switch name { + case componentattr.EdgeComponent: + m.ResetComponent() + return nil + } + return fmt.Errorf("unknown ComponentAttr edge %s", name) +} + +// IncidentMutation represents an operation that mutates the Incident nodes in the graph. +type IncidentMutation struct { + config + op Op + typ string + id *int + text *string + description *string + start_date *time.Time + end_date *time.Time + impact *int + addimpact *int + system *bool + _type *incident.Type + status *string + created_at *time.Time + modified_at *time.Time + deleted_at *time.Time + created_by *string + contact_email *string + version *int + addversion *int + clearedFields map[string]struct{} + components map[int]struct{} + removedcomponents map[int]struct{} + clearedcomponents bool + notifications map[int]struct{} + removednotifications map[int]struct{} + clearednotifications bool + done bool + oldValue func(context.Context) (*Incident, error) + predicates []predicate.Incident +} + +var _ ent.Mutation = (*IncidentMutation)(nil) + +// incidentOption allows management of the mutation configuration using functional options. +type incidentOption func(*IncidentMutation) + +// newIncidentMutation creates new mutation for the Incident entity. +func newIncidentMutation(c config, op Op, opts ...incidentOption) *IncidentMutation { + m := &IncidentMutation{ + config: c, + op: op, + typ: TypeIncident, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withIncidentID sets the ID field of the mutation. +func withIncidentID(id int) incidentOption { + return func(m *IncidentMutation) { + var ( + err error + once sync.Once + value *Incident + ) + m.oldValue = func(ctx context.Context) (*Incident, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Incident.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withIncident sets the old Incident of the mutation. +func withIncident(node *Incident) incidentOption { + return func(m *IncidentMutation) { + m.oldValue = func(context.Context) (*Incident, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m IncidentMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m IncidentMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of Incident entities. +func (m *IncidentMutation) SetID(id int) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *IncidentMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *IncidentMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Incident.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetText sets the "text" field. +func (m *IncidentMutation) SetText(s string) { + m.text = &s +} + +// Text returns the value of the "text" field in the mutation. +func (m *IncidentMutation) Text() (r string, exists bool) { + v := m.text + if v == nil { + return + } + return *v, true +} + +// OldText returns the old "text" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldText(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldText is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldText requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldText: %w", err) + } + return oldValue.Text, nil +} + +// ResetText resets all changes to the "text" field. +func (m *IncidentMutation) ResetText() { + m.text = nil +} + +// SetDescription sets the "description" field. +func (m *IncidentMutation) SetDescription(s string) { + m.description = &s +} + +// Description returns the value of the "description" field in the mutation. +func (m *IncidentMutation) Description() (r string, exists bool) { + v := m.description + if v == nil { + return + } + return *v, true +} + +// OldDescription returns the old "description" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldDescription(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDescription is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDescription requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDescription: %w", err) + } + return oldValue.Description, nil +} + +// ClearDescription clears the value of the "description" field. +func (m *IncidentMutation) ClearDescription() { + m.description = nil + m.clearedFields[incident.FieldDescription] = struct{}{} +} + +// DescriptionCleared returns if the "description" field was cleared in this mutation. +func (m *IncidentMutation) DescriptionCleared() bool { + _, ok := m.clearedFields[incident.FieldDescription] + return ok +} + +// ResetDescription resets all changes to the "description" field. +func (m *IncidentMutation) ResetDescription() { + m.description = nil + delete(m.clearedFields, incident.FieldDescription) +} + +// SetStartDate sets the "start_date" field. +func (m *IncidentMutation) SetStartDate(t time.Time) { + m.start_date = &t +} + +// StartDate returns the value of the "start_date" field in the mutation. +func (m *IncidentMutation) StartDate() (r time.Time, exists bool) { + v := m.start_date + if v == nil { + return + } + return *v, true +} + +// OldStartDate returns the old "start_date" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldStartDate(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStartDate is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStartDate requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStartDate: %w", err) + } + return oldValue.StartDate, nil +} + +// ResetStartDate resets all changes to the "start_date" field. +func (m *IncidentMutation) ResetStartDate() { + m.start_date = nil +} + +// SetEndDate sets the "end_date" field. +func (m *IncidentMutation) SetEndDate(t time.Time) { + m.end_date = &t +} + +// EndDate returns the value of the "end_date" field in the mutation. +func (m *IncidentMutation) EndDate() (r time.Time, exists bool) { + v := m.end_date + if v == nil { + return + } + return *v, true +} + +// OldEndDate returns the old "end_date" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldEndDate(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldEndDate is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldEndDate requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldEndDate: %w", err) + } + return oldValue.EndDate, nil +} + +// ClearEndDate clears the value of the "end_date" field. +func (m *IncidentMutation) ClearEndDate() { + m.end_date = nil + m.clearedFields[incident.FieldEndDate] = struct{}{} +} + +// EndDateCleared returns if the "end_date" field was cleared in this mutation. +func (m *IncidentMutation) EndDateCleared() bool { + _, ok := m.clearedFields[incident.FieldEndDate] + return ok +} + +// ResetEndDate resets all changes to the "end_date" field. +func (m *IncidentMutation) ResetEndDate() { + m.end_date = nil + delete(m.clearedFields, incident.FieldEndDate) +} + +// SetImpact sets the "impact" field. +func (m *IncidentMutation) SetImpact(i int) { + m.impact = &i + m.addimpact = nil +} + +// Impact returns the value of the "impact" field in the mutation. +func (m *IncidentMutation) Impact() (r int, exists bool) { + v := m.impact + if v == nil { + return + } + return *v, true +} + +// OldImpact returns the old "impact" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldImpact(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldImpact is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldImpact requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldImpact: %w", err) + } + return oldValue.Impact, nil +} + +// AddImpact adds i to the "impact" field. +func (m *IncidentMutation) AddImpact(i int) { + if m.addimpact != nil { + *m.addimpact += i + } else { + m.addimpact = &i + } +} + +// AddedImpact returns the value that was added to the "impact" field in this mutation. +func (m *IncidentMutation) AddedImpact() (r int, exists bool) { + v := m.addimpact + if v == nil { + return + } + return *v, true +} + +// ResetImpact resets all changes to the "impact" field. +func (m *IncidentMutation) ResetImpact() { + m.impact = nil + m.addimpact = nil +} + +// SetSystem sets the "system" field. +func (m *IncidentMutation) SetSystem(b bool) { + m.system = &b +} + +// System returns the value of the "system" field in the mutation. +func (m *IncidentMutation) System() (r bool, exists bool) { + v := m.system + if v == nil { + return + } + return *v, true +} + +// OldSystem returns the old "system" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldSystem(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSystem is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSystem requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSystem: %w", err) + } + return oldValue.System, nil +} + +// ResetSystem resets all changes to the "system" field. +func (m *IncidentMutation) ResetSystem() { + m.system = nil +} + +// SetType sets the "type" field. +func (m *IncidentMutation) SetType(i incident.Type) { + m._type = &i +} + +// GetType returns the value of the "type" field in the mutation. +func (m *IncidentMutation) GetType() (r incident.Type, exists bool) { + v := m._type + if v == nil { + return + } + return *v, true +} + +// OldType returns the old "type" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldType(ctx context.Context) (v incident.Type, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldType is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldType requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldType: %w", err) + } + return oldValue.Type, nil +} + +// ResetType resets all changes to the "type" field. +func (m *IncidentMutation) ResetType() { + m._type = nil +} + +// SetStatus sets the "status" field. +func (m *IncidentMutation) SetStatus(s string) { + m.status = &s +} + +// Status returns the value of the "status" field in the mutation. +func (m *IncidentMutation) Status() (r string, exists bool) { + v := m.status + if v == nil { + return + } + return *v, true +} + +// OldStatus returns the old "status" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldStatus(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStatus is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStatus requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStatus: %w", err) + } + return oldValue.Status, nil +} + +// ClearStatus clears the value of the "status" field. +func (m *IncidentMutation) ClearStatus() { + m.status = nil + m.clearedFields[incident.FieldStatus] = struct{}{} +} + +// StatusCleared returns if the "status" field was cleared in this mutation. +func (m *IncidentMutation) StatusCleared() bool { + _, ok := m.clearedFields[incident.FieldStatus] + return ok +} + +// ResetStatus resets all changes to the "status" field. +func (m *IncidentMutation) ResetStatus() { + m.status = nil + delete(m.clearedFields, incident.FieldStatus) +} + +// SetCreatedAt sets the "created_at" field. +func (m *IncidentMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *IncidentMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (m *IncidentMutation) ClearCreatedAt() { + m.created_at = nil + m.clearedFields[incident.FieldCreatedAt] = struct{}{} +} + +// CreatedAtCleared returns if the "created_at" field was cleared in this mutation. +func (m *IncidentMutation) CreatedAtCleared() bool { + _, ok := m.clearedFields[incident.FieldCreatedAt] + return ok +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *IncidentMutation) ResetCreatedAt() { + m.created_at = nil + delete(m.clearedFields, incident.FieldCreatedAt) +} + +// SetModifiedAt sets the "modified_at" field. +func (m *IncidentMutation) SetModifiedAt(t time.Time) { + m.modified_at = &t +} + +// ModifiedAt returns the value of the "modified_at" field in the mutation. +func (m *IncidentMutation) ModifiedAt() (r time.Time, exists bool) { + v := m.modified_at + if v == nil { + return + } + return *v, true +} + +// OldModifiedAt returns the old "modified_at" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldModifiedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldModifiedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldModifiedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldModifiedAt: %w", err) + } + return oldValue.ModifiedAt, nil +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (m *IncidentMutation) ClearModifiedAt() { + m.modified_at = nil + m.clearedFields[incident.FieldModifiedAt] = struct{}{} +} + +// ModifiedAtCleared returns if the "modified_at" field was cleared in this mutation. +func (m *IncidentMutation) ModifiedAtCleared() bool { + _, ok := m.clearedFields[incident.FieldModifiedAt] + return ok +} + +// ResetModifiedAt resets all changes to the "modified_at" field. +func (m *IncidentMutation) ResetModifiedAt() { + m.modified_at = nil + delete(m.clearedFields, incident.FieldModifiedAt) +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *IncidentMutation) SetDeletedAt(t time.Time) { + m.deleted_at = &t +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *IncidentMutation) DeletedAt() (r time.Time, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldDeletedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *IncidentMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[incident.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *IncidentMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[incident.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *IncidentMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, incident.FieldDeletedAt) +} + +// SetCreatedBy sets the "created_by" field. +func (m *IncidentMutation) SetCreatedBy(s string) { + m.created_by = &s +} + +// CreatedBy returns the value of the "created_by" field in the mutation. +func (m *IncidentMutation) CreatedBy() (r string, exists bool) { + v := m.created_by + if v == nil { + return + } + return *v, true +} + +// OldCreatedBy returns the old "created_by" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldCreatedBy(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedBy is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedBy requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedBy: %w", err) + } + return oldValue.CreatedBy, nil +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (m *IncidentMutation) ClearCreatedBy() { + m.created_by = nil + m.clearedFields[incident.FieldCreatedBy] = struct{}{} +} + +// CreatedByCleared returns if the "created_by" field was cleared in this mutation. +func (m *IncidentMutation) CreatedByCleared() bool { + _, ok := m.clearedFields[incident.FieldCreatedBy] + return ok +} + +// ResetCreatedBy resets all changes to the "created_by" field. +func (m *IncidentMutation) ResetCreatedBy() { + m.created_by = nil + delete(m.clearedFields, incident.FieldCreatedBy) +} + +// SetContactEmail sets the "contact_email" field. +func (m *IncidentMutation) SetContactEmail(s string) { + m.contact_email = &s +} + +// ContactEmail returns the value of the "contact_email" field in the mutation. +func (m *IncidentMutation) ContactEmail() (r string, exists bool) { + v := m.contact_email + if v == nil { + return + } + return *v, true +} + +// OldContactEmail returns the old "contact_email" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldContactEmail(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldContactEmail is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldContactEmail requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldContactEmail: %w", err) + } + return oldValue.ContactEmail, nil +} + +// ClearContactEmail clears the value of the "contact_email" field. +func (m *IncidentMutation) ClearContactEmail() { + m.contact_email = nil + m.clearedFields[incident.FieldContactEmail] = struct{}{} +} + +// ContactEmailCleared returns if the "contact_email" field was cleared in this mutation. +func (m *IncidentMutation) ContactEmailCleared() bool { + _, ok := m.clearedFields[incident.FieldContactEmail] + return ok +} + +// ResetContactEmail resets all changes to the "contact_email" field. +func (m *IncidentMutation) ResetContactEmail() { + m.contact_email = nil + delete(m.clearedFields, incident.FieldContactEmail) +} + +// SetVersion sets the "version" field. +func (m *IncidentMutation) SetVersion(i int) { + m.version = &i + m.addversion = nil +} + +// Version returns the value of the "version" field in the mutation. +func (m *IncidentMutation) Version() (r int, exists bool) { + v := m.version + if v == nil { + return + } + return *v, true +} + +// OldVersion returns the old "version" field's value of the Incident entity. +// If the Incident 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 *IncidentMutation) OldVersion(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldVersion is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldVersion requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldVersion: %w", err) + } + return oldValue.Version, nil +} + +// AddVersion adds i to the "version" field. +func (m *IncidentMutation) AddVersion(i int) { + if m.addversion != nil { + *m.addversion += i + } else { + m.addversion = &i + } +} + +// AddedVersion returns the value that was added to the "version" field in this mutation. +func (m *IncidentMutation) AddedVersion() (r int, exists bool) { + v := m.addversion + if v == nil { + return + } + return *v, true +} + +// ResetVersion resets all changes to the "version" field. +func (m *IncidentMutation) ResetVersion() { + m.version = nil + m.addversion = nil +} + +// AddComponentIDs adds the "components" edge to the Component entity by ids. +func (m *IncidentMutation) AddComponentIDs(ids ...int) { + if m.components == nil { + m.components = make(map[int]struct{}) + } + for i := range ids { + m.components[ids[i]] = struct{}{} + } +} + +// ClearComponents clears the "components" edge to the Component entity. +func (m *IncidentMutation) ClearComponents() { + m.clearedcomponents = true +} + +// ComponentsCleared reports if the "components" edge to the Component entity was cleared. +func (m *IncidentMutation) ComponentsCleared() bool { + return m.clearedcomponents +} + +// RemoveComponentIDs removes the "components" edge to the Component entity by IDs. +func (m *IncidentMutation) RemoveComponentIDs(ids ...int) { + if m.removedcomponents == nil { + m.removedcomponents = make(map[int]struct{}) + } + for i := range ids { + delete(m.components, ids[i]) + m.removedcomponents[ids[i]] = struct{}{} + } +} + +// RemovedComponents returns the removed IDs of the "components" edge to the Component entity. +func (m *IncidentMutation) RemovedComponentsIDs() (ids []int) { + for id := range m.removedcomponents { + ids = append(ids, id) + } + return +} + +// ComponentsIDs returns the "components" edge IDs in the mutation. +func (m *IncidentMutation) ComponentsIDs() (ids []int) { + for id := range m.components { + ids = append(ids, id) + } + return +} + +// ResetComponents resets all changes to the "components" edge. +func (m *IncidentMutation) ResetComponents() { + m.components = nil + m.clearedcomponents = false + m.removedcomponents = nil +} + +// AddNotificationIDs adds the "notifications" edge to the NotificationOutbox entity by ids. +func (m *IncidentMutation) AddNotificationIDs(ids ...int) { + if m.notifications == nil { + m.notifications = make(map[int]struct{}) + } + for i := range ids { + m.notifications[ids[i]] = struct{}{} + } +} + +// ClearNotifications clears the "notifications" edge to the NotificationOutbox entity. +func (m *IncidentMutation) ClearNotifications() { + m.clearednotifications = true +} + +// NotificationsCleared reports if the "notifications" edge to the NotificationOutbox entity was cleared. +func (m *IncidentMutation) NotificationsCleared() bool { + return m.clearednotifications +} + +// RemoveNotificationIDs removes the "notifications" edge to the NotificationOutbox entity by IDs. +func (m *IncidentMutation) RemoveNotificationIDs(ids ...int) { + if m.removednotifications == nil { + m.removednotifications = make(map[int]struct{}) + } + for i := range ids { + delete(m.notifications, ids[i]) + m.removednotifications[ids[i]] = struct{}{} + } +} + +// RemovedNotifications returns the removed IDs of the "notifications" edge to the NotificationOutbox entity. +func (m *IncidentMutation) RemovedNotificationsIDs() (ids []int) { + for id := range m.removednotifications { + ids = append(ids, id) + } + return +} + +// NotificationsIDs returns the "notifications" edge IDs in the mutation. +func (m *IncidentMutation) NotificationsIDs() (ids []int) { + for id := range m.notifications { + ids = append(ids, id) + } + return +} + +// ResetNotifications resets all changes to the "notifications" edge. +func (m *IncidentMutation) ResetNotifications() { + m.notifications = nil + m.clearednotifications = false + m.removednotifications = nil +} + +// Where appends a list predicates to the IncidentMutation builder. +func (m *IncidentMutation) Where(ps ...predicate.Incident) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the IncidentMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *IncidentMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.Incident, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *IncidentMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *IncidentMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (Incident). +func (m *IncidentMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *IncidentMutation) Fields() []string { + fields := make([]string, 0, 14) + if m.text != nil { + fields = append(fields, incident.FieldText) + } + if m.description != nil { + fields = append(fields, incident.FieldDescription) + } + if m.start_date != nil { + fields = append(fields, incident.FieldStartDate) + } + if m.end_date != nil { + fields = append(fields, incident.FieldEndDate) + } + if m.impact != nil { + fields = append(fields, incident.FieldImpact) + } + if m.system != nil { + fields = append(fields, incident.FieldSystem) + } + if m._type != nil { + fields = append(fields, incident.FieldType) + } + if m.status != nil { + fields = append(fields, incident.FieldStatus) + } + if m.created_at != nil { + fields = append(fields, incident.FieldCreatedAt) + } + if m.modified_at != nil { + fields = append(fields, incident.FieldModifiedAt) + } + if m.deleted_at != nil { + fields = append(fields, incident.FieldDeletedAt) + } + if m.created_by != nil { + fields = append(fields, incident.FieldCreatedBy) + } + if m.contact_email != nil { + fields = append(fields, incident.FieldContactEmail) + } + if m.version != nil { + fields = append(fields, incident.FieldVersion) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *IncidentMutation) Field(name string) (ent.Value, bool) { + switch name { + case incident.FieldText: + return m.Text() + case incident.FieldDescription: + return m.Description() + case incident.FieldStartDate: + return m.StartDate() + case incident.FieldEndDate: + return m.EndDate() + case incident.FieldImpact: + return m.Impact() + case incident.FieldSystem: + return m.System() + case incident.FieldType: + return m.GetType() + case incident.FieldStatus: + return m.Status() + case incident.FieldCreatedAt: + return m.CreatedAt() + case incident.FieldModifiedAt: + return m.ModifiedAt() + case incident.FieldDeletedAt: + return m.DeletedAt() + case incident.FieldCreatedBy: + return m.CreatedBy() + case incident.FieldContactEmail: + return m.ContactEmail() + case incident.FieldVersion: + return m.Version() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *IncidentMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case incident.FieldText: + return m.OldText(ctx) + case incident.FieldDescription: + return m.OldDescription(ctx) + case incident.FieldStartDate: + return m.OldStartDate(ctx) + case incident.FieldEndDate: + return m.OldEndDate(ctx) + case incident.FieldImpact: + return m.OldImpact(ctx) + case incident.FieldSystem: + return m.OldSystem(ctx) + case incident.FieldType: + return m.OldType(ctx) + case incident.FieldStatus: + return m.OldStatus(ctx) + case incident.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case incident.FieldModifiedAt: + return m.OldModifiedAt(ctx) + case incident.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case incident.FieldCreatedBy: + return m.OldCreatedBy(ctx) + case incident.FieldContactEmail: + return m.OldContactEmail(ctx) + case incident.FieldVersion: + return m.OldVersion(ctx) + } + return nil, fmt.Errorf("unknown Incident field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *IncidentMutation) SetField(name string, value ent.Value) error { + switch name { + case incident.FieldText: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetText(v) + return nil + case incident.FieldDescription: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDescription(v) + return nil + case incident.FieldStartDate: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStartDate(v) + return nil + case incident.FieldEndDate: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetEndDate(v) + return nil + case incident.FieldImpact: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetImpact(v) + return nil + case incident.FieldSystem: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSystem(v) + return nil + case incident.FieldType: + v, ok := value.(incident.Type) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetType(v) + return nil + case incident.FieldStatus: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStatus(v) + return nil + case incident.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case incident.FieldModifiedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetModifiedAt(v) + return nil + case incident.FieldDeletedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case incident.FieldCreatedBy: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedBy(v) + return nil + case incident.FieldContactEmail: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetContactEmail(v) + return nil + case incident.FieldVersion: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetVersion(v) + return nil + } + return fmt.Errorf("unknown Incident field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *IncidentMutation) AddedFields() []string { + var fields []string + if m.addimpact != nil { + fields = append(fields, incident.FieldImpact) + } + if m.addversion != nil { + fields = append(fields, incident.FieldVersion) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *IncidentMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case incident.FieldImpact: + return m.AddedImpact() + case incident.FieldVersion: + return m.AddedVersion() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *IncidentMutation) AddField(name string, value ent.Value) error { + switch name { + case incident.FieldImpact: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddImpact(v) + return nil + case incident.FieldVersion: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddVersion(v) + return nil + } + return fmt.Errorf("unknown Incident numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *IncidentMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(incident.FieldDescription) { + fields = append(fields, incident.FieldDescription) + } + if m.FieldCleared(incident.FieldEndDate) { + fields = append(fields, incident.FieldEndDate) + } + if m.FieldCleared(incident.FieldStatus) { + fields = append(fields, incident.FieldStatus) + } + if m.FieldCleared(incident.FieldCreatedAt) { + fields = append(fields, incident.FieldCreatedAt) + } + if m.FieldCleared(incident.FieldModifiedAt) { + fields = append(fields, incident.FieldModifiedAt) + } + if m.FieldCleared(incident.FieldDeletedAt) { + fields = append(fields, incident.FieldDeletedAt) + } + if m.FieldCleared(incident.FieldCreatedBy) { + fields = append(fields, incident.FieldCreatedBy) + } + if m.FieldCleared(incident.FieldContactEmail) { + fields = append(fields, incident.FieldContactEmail) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *IncidentMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *IncidentMutation) ClearField(name string) error { + switch name { + case incident.FieldDescription: + m.ClearDescription() + return nil + case incident.FieldEndDate: + m.ClearEndDate() + return nil + case incident.FieldStatus: + m.ClearStatus() + return nil + case incident.FieldCreatedAt: + m.ClearCreatedAt() + return nil + case incident.FieldModifiedAt: + m.ClearModifiedAt() + return nil + case incident.FieldDeletedAt: + m.ClearDeletedAt() + return nil + case incident.FieldCreatedBy: + m.ClearCreatedBy() + return nil + case incident.FieldContactEmail: + m.ClearContactEmail() + return nil + } + return fmt.Errorf("unknown Incident nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *IncidentMutation) ResetField(name string) error { + switch name { + case incident.FieldText: + m.ResetText() + return nil + case incident.FieldDescription: + m.ResetDescription() + return nil + case incident.FieldStartDate: + m.ResetStartDate() + return nil + case incident.FieldEndDate: + m.ResetEndDate() + return nil + case incident.FieldImpact: + m.ResetImpact() + return nil + case incident.FieldSystem: + m.ResetSystem() + return nil + case incident.FieldType: + m.ResetType() + return nil + case incident.FieldStatus: + m.ResetStatus() + return nil + case incident.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case incident.FieldModifiedAt: + m.ResetModifiedAt() + return nil + case incident.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case incident.FieldCreatedBy: + m.ResetCreatedBy() + return nil + case incident.FieldContactEmail: + m.ResetContactEmail() + return nil + case incident.FieldVersion: + m.ResetVersion() + return nil + } + return fmt.Errorf("unknown Incident field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *IncidentMutation) AddedEdges() []string { + edges := make([]string, 0, 2) + if m.components != nil { + edges = append(edges, incident.EdgeComponents) + } + if m.notifications != nil { + edges = append(edges, incident.EdgeNotifications) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *IncidentMutation) AddedIDs(name string) []ent.Value { + switch name { + case incident.EdgeComponents: + ids := make([]ent.Value, 0, len(m.components)) + for id := range m.components { + ids = append(ids, id) + } + return ids + case incident.EdgeNotifications: + ids := make([]ent.Value, 0, len(m.notifications)) + for id := range m.notifications { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *IncidentMutation) RemovedEdges() []string { + edges := make([]string, 0, 2) + if m.removedcomponents != nil { + edges = append(edges, incident.EdgeComponents) + } + if m.removednotifications != nil { + edges = append(edges, incident.EdgeNotifications) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *IncidentMutation) RemovedIDs(name string) []ent.Value { + switch name { + case incident.EdgeComponents: + ids := make([]ent.Value, 0, len(m.removedcomponents)) + for id := range m.removedcomponents { + ids = append(ids, id) + } + return ids + case incident.EdgeNotifications: + ids := make([]ent.Value, 0, len(m.removednotifications)) + for id := range m.removednotifications { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *IncidentMutation) ClearedEdges() []string { + edges := make([]string, 0, 2) + if m.clearedcomponents { + edges = append(edges, incident.EdgeComponents) + } + if m.clearednotifications { + edges = append(edges, incident.EdgeNotifications) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *IncidentMutation) EdgeCleared(name string) bool { + switch name { + case incident.EdgeComponents: + return m.clearedcomponents + case incident.EdgeNotifications: + return m.clearednotifications + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *IncidentMutation) ClearEdge(name string) error { + switch name { + } + return fmt.Errorf("unknown Incident unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *IncidentMutation) ResetEdge(name string) error { + switch name { + case incident.EdgeComponents: + m.ResetComponents() + return nil + case incident.EdgeNotifications: + m.ResetNotifications() + return nil + } + return fmt.Errorf("unknown Incident edge %s", name) +} + +// IncidentStatusMutation represents an operation that mutates the IncidentStatus nodes in the graph. +type IncidentStatusMutation struct { + config + op Op + typ string + id *int + incident_id *int + addincident_id *int + timestamp *time.Time + text *string + status *string + created_at *time.Time + modified_at *time.Time + deleted_at *time.Time + created_by *string + modified_by *string + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*IncidentStatus, error) + predicates []predicate.IncidentStatus +} + +var _ ent.Mutation = (*IncidentStatusMutation)(nil) + +// incidentstatusOption allows management of the mutation configuration using functional options. +type incidentstatusOption func(*IncidentStatusMutation) + +// newIncidentStatusMutation creates new mutation for the IncidentStatus entity. +func newIncidentStatusMutation(c config, op Op, opts ...incidentstatusOption) *IncidentStatusMutation { + m := &IncidentStatusMutation{ + config: c, + op: op, + typ: TypeIncidentStatus, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withIncidentStatusID sets the ID field of the mutation. +func withIncidentStatusID(id int) incidentstatusOption { + return func(m *IncidentStatusMutation) { + var ( + err error + once sync.Once + value *IncidentStatus + ) + m.oldValue = func(ctx context.Context) (*IncidentStatus, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().IncidentStatus.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withIncidentStatus sets the old IncidentStatus of the mutation. +func withIncidentStatus(node *IncidentStatus) incidentstatusOption { + return func(m *IncidentStatusMutation) { + m.oldValue = func(context.Context) (*IncidentStatus, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m IncidentStatusMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m IncidentStatusMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of IncidentStatus entities. +func (m *IncidentStatusMutation) SetID(id int) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *IncidentStatusMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *IncidentStatusMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().IncidentStatus.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetIncidentID sets the "incident_id" field. +func (m *IncidentStatusMutation) SetIncidentID(i int) { + m.incident_id = &i + m.addincident_id = nil +} + +// IncidentID returns the value of the "incident_id" field in the mutation. +func (m *IncidentStatusMutation) IncidentID() (r int, exists bool) { + v := m.incident_id + if v == nil { + return + } + return *v, true +} + +// OldIncidentID returns the old "incident_id" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldIncidentID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldIncidentID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldIncidentID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldIncidentID: %w", err) + } + return oldValue.IncidentID, nil +} + +// AddIncidentID adds i to the "incident_id" field. +func (m *IncidentStatusMutation) AddIncidentID(i int) { + if m.addincident_id != nil { + *m.addincident_id += i + } else { + m.addincident_id = &i + } +} + +// AddedIncidentID returns the value that was added to the "incident_id" field in this mutation. +func (m *IncidentStatusMutation) AddedIncidentID() (r int, exists bool) { + v := m.addincident_id + if v == nil { + return + } + return *v, true +} + +// ClearIncidentID clears the value of the "incident_id" field. +func (m *IncidentStatusMutation) ClearIncidentID() { + m.incident_id = nil + m.addincident_id = nil + m.clearedFields[incidentstatus.FieldIncidentID] = struct{}{} +} + +// IncidentIDCleared returns if the "incident_id" field was cleared in this mutation. +func (m *IncidentStatusMutation) IncidentIDCleared() bool { + _, ok := m.clearedFields[incidentstatus.FieldIncidentID] + return ok +} + +// ResetIncidentID resets all changes to the "incident_id" field. +func (m *IncidentStatusMutation) ResetIncidentID() { + m.incident_id = nil + m.addincident_id = nil + delete(m.clearedFields, incidentstatus.FieldIncidentID) +} + +// SetTimestamp sets the "timestamp" field. +func (m *IncidentStatusMutation) SetTimestamp(t time.Time) { + m.timestamp = &t +} + +// Timestamp returns the value of the "timestamp" field in the mutation. +func (m *IncidentStatusMutation) Timestamp() (r time.Time, exists bool) { + v := m.timestamp + if v == nil { + return + } + return *v, true +} + +// OldTimestamp returns the old "timestamp" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldTimestamp(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTimestamp is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTimestamp requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTimestamp: %w", err) + } + return oldValue.Timestamp, nil +} + +// ResetTimestamp resets all changes to the "timestamp" field. +func (m *IncidentStatusMutation) ResetTimestamp() { + m.timestamp = nil +} + +// SetText sets the "text" field. +func (m *IncidentStatusMutation) SetText(s string) { + m.text = &s +} + +// Text returns the value of the "text" field in the mutation. +func (m *IncidentStatusMutation) Text() (r string, exists bool) { + v := m.text + if v == nil { + return + } + return *v, true +} + +// OldText returns the old "text" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldText(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldText is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldText requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldText: %w", err) + } + return oldValue.Text, nil +} + +// ResetText resets all changes to the "text" field. +func (m *IncidentStatusMutation) ResetText() { + m.text = nil +} + +// SetStatus sets the "status" field. +func (m *IncidentStatusMutation) SetStatus(s string) { + m.status = &s +} + +// Status returns the value of the "status" field in the mutation. +func (m *IncidentStatusMutation) Status() (r string, exists bool) { + v := m.status + if v == nil { + return + } + return *v, true +} + +// OldStatus returns the old "status" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldStatus(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStatus is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStatus requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStatus: %w", err) + } + return oldValue.Status, nil +} + +// ResetStatus resets all changes to the "status" field. +func (m *IncidentStatusMutation) ResetStatus() { + m.status = nil +} + +// SetCreatedAt sets the "created_at" field. +func (m *IncidentStatusMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *IncidentStatusMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ClearCreatedAt clears the value of the "created_at" field. +func (m *IncidentStatusMutation) ClearCreatedAt() { + m.created_at = nil + m.clearedFields[incidentstatus.FieldCreatedAt] = struct{}{} +} + +// CreatedAtCleared returns if the "created_at" field was cleared in this mutation. +func (m *IncidentStatusMutation) CreatedAtCleared() bool { + _, ok := m.clearedFields[incidentstatus.FieldCreatedAt] + return ok +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *IncidentStatusMutation) ResetCreatedAt() { + m.created_at = nil + delete(m.clearedFields, incidentstatus.FieldCreatedAt) +} + +// SetModifiedAt sets the "modified_at" field. +func (m *IncidentStatusMutation) SetModifiedAt(t time.Time) { + m.modified_at = &t +} + +// ModifiedAt returns the value of the "modified_at" field in the mutation. +func (m *IncidentStatusMutation) ModifiedAt() (r time.Time, exists bool) { + v := m.modified_at + if v == nil { + return + } + return *v, true +} + +// OldModifiedAt returns the old "modified_at" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldModifiedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldModifiedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldModifiedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldModifiedAt: %w", err) + } + return oldValue.ModifiedAt, nil +} + +// ClearModifiedAt clears the value of the "modified_at" field. +func (m *IncidentStatusMutation) ClearModifiedAt() { + m.modified_at = nil + m.clearedFields[incidentstatus.FieldModifiedAt] = struct{}{} +} + +// ModifiedAtCleared returns if the "modified_at" field was cleared in this mutation. +func (m *IncidentStatusMutation) ModifiedAtCleared() bool { + _, ok := m.clearedFields[incidentstatus.FieldModifiedAt] + return ok +} + +// ResetModifiedAt resets all changes to the "modified_at" field. +func (m *IncidentStatusMutation) ResetModifiedAt() { + m.modified_at = nil + delete(m.clearedFields, incidentstatus.FieldModifiedAt) +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *IncidentStatusMutation) SetDeletedAt(t time.Time) { + m.deleted_at = &t +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *IncidentStatusMutation) DeletedAt() (r time.Time, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldDeletedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *IncidentStatusMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[incidentstatus.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *IncidentStatusMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[incidentstatus.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *IncidentStatusMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, incidentstatus.FieldDeletedAt) +} + +// SetCreatedBy sets the "created_by" field. +func (m *IncidentStatusMutation) SetCreatedBy(s string) { + m.created_by = &s +} + +// CreatedBy returns the value of the "created_by" field in the mutation. +func (m *IncidentStatusMutation) CreatedBy() (r string, exists bool) { + v := m.created_by + if v == nil { + return + } + return *v, true +} + +// OldCreatedBy returns the old "created_by" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldCreatedBy(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedBy is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedBy requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedBy: %w", err) + } + return oldValue.CreatedBy, nil +} + +// ClearCreatedBy clears the value of the "created_by" field. +func (m *IncidentStatusMutation) ClearCreatedBy() { + m.created_by = nil + m.clearedFields[incidentstatus.FieldCreatedBy] = struct{}{} +} + +// CreatedByCleared returns if the "created_by" field was cleared in this mutation. +func (m *IncidentStatusMutation) CreatedByCleared() bool { + _, ok := m.clearedFields[incidentstatus.FieldCreatedBy] + return ok +} + +// ResetCreatedBy resets all changes to the "created_by" field. +func (m *IncidentStatusMutation) ResetCreatedBy() { + m.created_by = nil + delete(m.clearedFields, incidentstatus.FieldCreatedBy) +} + +// SetModifiedBy sets the "modified_by" field. +func (m *IncidentStatusMutation) SetModifiedBy(s string) { + m.modified_by = &s +} + +// ModifiedBy returns the value of the "modified_by" field in the mutation. +func (m *IncidentStatusMutation) ModifiedBy() (r string, exists bool) { + v := m.modified_by + if v == nil { + return + } + return *v, true +} + +// OldModifiedBy returns the old "modified_by" field's value of the IncidentStatus entity. +// If the IncidentStatus 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 *IncidentStatusMutation) OldModifiedBy(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldModifiedBy is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldModifiedBy requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldModifiedBy: %w", err) + } + return oldValue.ModifiedBy, nil +} + +// ClearModifiedBy clears the value of the "modified_by" field. +func (m *IncidentStatusMutation) ClearModifiedBy() { + m.modified_by = nil + m.clearedFields[incidentstatus.FieldModifiedBy] = struct{}{} +} + +// ModifiedByCleared returns if the "modified_by" field was cleared in this mutation. +func (m *IncidentStatusMutation) ModifiedByCleared() bool { + _, ok := m.clearedFields[incidentstatus.FieldModifiedBy] + return ok +} + +// ResetModifiedBy resets all changes to the "modified_by" field. +func (m *IncidentStatusMutation) ResetModifiedBy() { + m.modified_by = nil + delete(m.clearedFields, incidentstatus.FieldModifiedBy) +} + +// Where appends a list predicates to the IncidentStatusMutation builder. +func (m *IncidentStatusMutation) Where(ps ...predicate.IncidentStatus) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the IncidentStatusMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *IncidentStatusMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.IncidentStatus, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *IncidentStatusMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *IncidentStatusMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (IncidentStatus). +func (m *IncidentStatusMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *IncidentStatusMutation) Fields() []string { + fields := make([]string, 0, 9) + if m.incident_id != nil { + fields = append(fields, incidentstatus.FieldIncidentID) + } + if m.timestamp != nil { + fields = append(fields, incidentstatus.FieldTimestamp) + } + if m.text != nil { + fields = append(fields, incidentstatus.FieldText) + } + if m.status != nil { + fields = append(fields, incidentstatus.FieldStatus) + } + if m.created_at != nil { + fields = append(fields, incidentstatus.FieldCreatedAt) + } + if m.modified_at != nil { + fields = append(fields, incidentstatus.FieldModifiedAt) + } + if m.deleted_at != nil { + fields = append(fields, incidentstatus.FieldDeletedAt) + } + if m.created_by != nil { + fields = append(fields, incidentstatus.FieldCreatedBy) + } + if m.modified_by != nil { + fields = append(fields, incidentstatus.FieldModifiedBy) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *IncidentStatusMutation) Field(name string) (ent.Value, bool) { + switch name { + case incidentstatus.FieldIncidentID: + return m.IncidentID() + case incidentstatus.FieldTimestamp: + return m.Timestamp() + case incidentstatus.FieldText: + return m.Text() + case incidentstatus.FieldStatus: + return m.Status() + case incidentstatus.FieldCreatedAt: + return m.CreatedAt() + case incidentstatus.FieldModifiedAt: + return m.ModifiedAt() + case incidentstatus.FieldDeletedAt: + return m.DeletedAt() + case incidentstatus.FieldCreatedBy: + return m.CreatedBy() + case incidentstatus.FieldModifiedBy: + return m.ModifiedBy() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *IncidentStatusMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case incidentstatus.FieldIncidentID: + return m.OldIncidentID(ctx) + case incidentstatus.FieldTimestamp: + return m.OldTimestamp(ctx) + case incidentstatus.FieldText: + return m.OldText(ctx) + case incidentstatus.FieldStatus: + return m.OldStatus(ctx) + case incidentstatus.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case incidentstatus.FieldModifiedAt: + return m.OldModifiedAt(ctx) + case incidentstatus.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case incidentstatus.FieldCreatedBy: + return m.OldCreatedBy(ctx) + case incidentstatus.FieldModifiedBy: + return m.OldModifiedBy(ctx) + } + return nil, fmt.Errorf("unknown IncidentStatus field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *IncidentStatusMutation) SetField(name string, value ent.Value) error { + switch name { + case incidentstatus.FieldIncidentID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetIncidentID(v) + return nil + case incidentstatus.FieldTimestamp: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTimestamp(v) + return nil + case incidentstatus.FieldText: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetText(v) + return nil + case incidentstatus.FieldStatus: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStatus(v) + return nil + case incidentstatus.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case incidentstatus.FieldModifiedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetModifiedAt(v) + return nil + case incidentstatus.FieldDeletedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case incidentstatus.FieldCreatedBy: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedBy(v) + return nil + case incidentstatus.FieldModifiedBy: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetModifiedBy(v) + return nil + } + return fmt.Errorf("unknown IncidentStatus field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *IncidentStatusMutation) AddedFields() []string { + var fields []string + if m.addincident_id != nil { + fields = append(fields, incidentstatus.FieldIncidentID) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *IncidentStatusMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case incidentstatus.FieldIncidentID: + return m.AddedIncidentID() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *IncidentStatusMutation) AddField(name string, value ent.Value) error { + switch name { + case incidentstatus.FieldIncidentID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddIncidentID(v) + return nil + } + return fmt.Errorf("unknown IncidentStatus numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *IncidentStatusMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(incidentstatus.FieldIncidentID) { + fields = append(fields, incidentstatus.FieldIncidentID) + } + if m.FieldCleared(incidentstatus.FieldCreatedAt) { + fields = append(fields, incidentstatus.FieldCreatedAt) + } + if m.FieldCleared(incidentstatus.FieldModifiedAt) { + fields = append(fields, incidentstatus.FieldModifiedAt) + } + if m.FieldCleared(incidentstatus.FieldDeletedAt) { + fields = append(fields, incidentstatus.FieldDeletedAt) + } + if m.FieldCleared(incidentstatus.FieldCreatedBy) { + fields = append(fields, incidentstatus.FieldCreatedBy) + } + if m.FieldCleared(incidentstatus.FieldModifiedBy) { + fields = append(fields, incidentstatus.FieldModifiedBy) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *IncidentStatusMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *IncidentStatusMutation) ClearField(name string) error { + switch name { + case incidentstatus.FieldIncidentID: + m.ClearIncidentID() + return nil + case incidentstatus.FieldCreatedAt: + m.ClearCreatedAt() + return nil + case incidentstatus.FieldModifiedAt: + m.ClearModifiedAt() + return nil + case incidentstatus.FieldDeletedAt: + m.ClearDeletedAt() + return nil + case incidentstatus.FieldCreatedBy: + m.ClearCreatedBy() + return nil + case incidentstatus.FieldModifiedBy: + m.ClearModifiedBy() + return nil + } + return fmt.Errorf("unknown IncidentStatus nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *IncidentStatusMutation) ResetField(name string) error { + switch name { + case incidentstatus.FieldIncidentID: + m.ResetIncidentID() + return nil + case incidentstatus.FieldTimestamp: + m.ResetTimestamp() + return nil + case incidentstatus.FieldText: + m.ResetText() + return nil + case incidentstatus.FieldStatus: + m.ResetStatus() + return nil + case incidentstatus.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case incidentstatus.FieldModifiedAt: + m.ResetModifiedAt() + return nil + case incidentstatus.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case incidentstatus.FieldCreatedBy: + m.ResetCreatedBy() + return nil + case incidentstatus.FieldModifiedBy: + m.ResetModifiedBy() + return nil + } + return fmt.Errorf("unknown IncidentStatus field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *IncidentStatusMutation) AddedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *IncidentStatusMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *IncidentStatusMutation) RemovedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *IncidentStatusMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *IncidentStatusMutation) ClearedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *IncidentStatusMutation) EdgeCleared(name string) bool { + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *IncidentStatusMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown IncidentStatus unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *IncidentStatusMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown IncidentStatus edge %s", name) +} + +// NotificationOutboxMutation represents an operation that mutates the NotificationOutbox nodes in the graph. +type NotificationOutboxMutation struct { + config + op Op + typ string + id *int + kind *string + recipient *string + payload *map[string]interface{} + change_id *string + dedup_key *string + status *string + attempts *int + addattempts *int + next_attempt_at *time.Time + locked_by *string + locked_at *time.Time + last_error *string + created_at *time.Time + updated_at *time.Time + clearedFields map[string]struct{} + incident *int + clearedincident bool + done bool + oldValue func(context.Context) (*NotificationOutbox, error) + predicates []predicate.NotificationOutbox +} + +var _ ent.Mutation = (*NotificationOutboxMutation)(nil) + +// notificationoutboxOption allows management of the mutation configuration using functional options. +type notificationoutboxOption func(*NotificationOutboxMutation) + +// newNotificationOutboxMutation creates new mutation for the NotificationOutbox entity. +func newNotificationOutboxMutation(c config, op Op, opts ...notificationoutboxOption) *NotificationOutboxMutation { + m := &NotificationOutboxMutation{ + config: c, + op: op, + typ: TypeNotificationOutbox, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withNotificationOutboxID sets the ID field of the mutation. +func withNotificationOutboxID(id int) notificationoutboxOption { + return func(m *NotificationOutboxMutation) { + var ( + err error + once sync.Once + value *NotificationOutbox + ) + m.oldValue = func(ctx context.Context) (*NotificationOutbox, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().NotificationOutbox.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withNotificationOutbox sets the old NotificationOutbox of the mutation. +func withNotificationOutbox(node *NotificationOutbox) notificationoutboxOption { + return func(m *NotificationOutboxMutation) { + m.oldValue = func(context.Context) (*NotificationOutbox, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m NotificationOutboxMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m NotificationOutboxMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of NotificationOutbox entities. +func (m *NotificationOutboxMutation) SetID(id int) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *NotificationOutboxMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *NotificationOutboxMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().NotificationOutbox.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetKind sets the "kind" field. +func (m *NotificationOutboxMutation) SetKind(s string) { + m.kind = &s +} + +// Kind returns the value of the "kind" field in the mutation. +func (m *NotificationOutboxMutation) Kind() (r string, exists bool) { + v := m.kind + if v == nil { + return + } + return *v, true +} + +// OldKind returns the old "kind" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldKind(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldKind is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldKind requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldKind: %w", err) + } + return oldValue.Kind, nil +} + +// ResetKind resets all changes to the "kind" field. +func (m *NotificationOutboxMutation) ResetKind() { + m.kind = nil +} + +// SetIncidentID sets the "incident_id" field. +func (m *NotificationOutboxMutation) SetIncidentID(i int) { + m.incident = &i +} + +// IncidentID returns the value of the "incident_id" field in the mutation. +func (m *NotificationOutboxMutation) IncidentID() (r int, exists bool) { + v := m.incident + if v == nil { + return + } + return *v, true +} + +// OldIncidentID returns the old "incident_id" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldIncidentID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldIncidentID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldIncidentID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldIncidentID: %w", err) + } + return oldValue.IncidentID, nil +} + +// ResetIncidentID resets all changes to the "incident_id" field. +func (m *NotificationOutboxMutation) ResetIncidentID() { + m.incident = nil +} + +// SetRecipient sets the "recipient" field. +func (m *NotificationOutboxMutation) SetRecipient(s string) { + m.recipient = &s +} + +// Recipient returns the value of the "recipient" field in the mutation. +func (m *NotificationOutboxMutation) Recipient() (r string, exists bool) { + v := m.recipient + if v == nil { + return + } + return *v, true +} + +// OldRecipient returns the old "recipient" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldRecipient(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldRecipient is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldRecipient requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldRecipient: %w", err) + } + return oldValue.Recipient, nil +} + +// ResetRecipient resets all changes to the "recipient" field. +func (m *NotificationOutboxMutation) ResetRecipient() { + m.recipient = nil +} + +// SetPayload sets the "payload" field. +func (m *NotificationOutboxMutation) SetPayload(value map[string]interface{}) { + m.payload = &value +} + +// Payload returns the value of the "payload" field in the mutation. +func (m *NotificationOutboxMutation) Payload() (r map[string]interface{}, exists bool) { + v := m.payload + if v == nil { + return + } + return *v, true +} + +// OldPayload returns the old "payload" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldPayload(ctx context.Context) (v map[string]interface{}, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldPayload is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldPayload requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldPayload: %w", err) + } + return oldValue.Payload, nil +} + +// ResetPayload resets all changes to the "payload" field. +func (m *NotificationOutboxMutation) ResetPayload() { + m.payload = nil +} + +// SetChangeID sets the "change_id" field. +func (m *NotificationOutboxMutation) SetChangeID(s string) { + m.change_id = &s +} + +// ChangeID returns the value of the "change_id" field in the mutation. +func (m *NotificationOutboxMutation) ChangeID() (r string, exists bool) { + v := m.change_id + if v == nil { + return + } + return *v, true +} + +// OldChangeID returns the old "change_id" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldChangeID(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldChangeID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldChangeID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldChangeID: %w", err) + } + return oldValue.ChangeID, nil +} + +// ResetChangeID resets all changes to the "change_id" field. +func (m *NotificationOutboxMutation) ResetChangeID() { + m.change_id = nil +} + +// SetDedupKey sets the "dedup_key" field. +func (m *NotificationOutboxMutation) SetDedupKey(s string) { + m.dedup_key = &s +} + +// DedupKey returns the value of the "dedup_key" field in the mutation. +func (m *NotificationOutboxMutation) DedupKey() (r string, exists bool) { + v := m.dedup_key + if v == nil { + return + } + return *v, true +} + +// OldDedupKey returns the old "dedup_key" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldDedupKey(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDedupKey is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDedupKey requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDedupKey: %w", err) + } + return oldValue.DedupKey, nil +} + +// ResetDedupKey resets all changes to the "dedup_key" field. +func (m *NotificationOutboxMutation) ResetDedupKey() { + m.dedup_key = nil +} + +// SetStatus sets the "status" field. +func (m *NotificationOutboxMutation) SetStatus(s string) { + m.status = &s +} + +// Status returns the value of the "status" field in the mutation. +func (m *NotificationOutboxMutation) Status() (r string, exists bool) { + v := m.status + if v == nil { + return + } + return *v, true +} + +// OldStatus returns the old "status" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldStatus(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStatus is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStatus requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStatus: %w", err) + } + return oldValue.Status, nil +} + +// ResetStatus resets all changes to the "status" field. +func (m *NotificationOutboxMutation) ResetStatus() { + m.status = nil +} + +// SetAttempts sets the "attempts" field. +func (m *NotificationOutboxMutation) SetAttempts(i int) { + m.attempts = &i + m.addattempts = nil +} + +// Attempts returns the value of the "attempts" field in the mutation. +func (m *NotificationOutboxMutation) Attempts() (r int, exists bool) { + v := m.attempts + if v == nil { + return + } + return *v, true +} + +// OldAttempts returns the old "attempts" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldAttempts(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldAttempts is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldAttempts requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldAttempts: %w", err) + } + return oldValue.Attempts, nil +} + +// AddAttempts adds i to the "attempts" field. +func (m *NotificationOutboxMutation) AddAttempts(i int) { + if m.addattempts != nil { + *m.addattempts += i + } else { + m.addattempts = &i + } +} + +// AddedAttempts returns the value that was added to the "attempts" field in this mutation. +func (m *NotificationOutboxMutation) AddedAttempts() (r int, exists bool) { + v := m.addattempts + if v == nil { + return + } + return *v, true +} + +// ResetAttempts resets all changes to the "attempts" field. +func (m *NotificationOutboxMutation) ResetAttempts() { + m.attempts = nil + m.addattempts = nil +} + +// SetNextAttemptAt sets the "next_attempt_at" field. +func (m *NotificationOutboxMutation) SetNextAttemptAt(t time.Time) { + m.next_attempt_at = &t +} + +// NextAttemptAt returns the value of the "next_attempt_at" field in the mutation. +func (m *NotificationOutboxMutation) NextAttemptAt() (r time.Time, exists bool) { + v := m.next_attempt_at + if v == nil { + return + } + return *v, true +} + +// OldNextAttemptAt returns the old "next_attempt_at" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldNextAttemptAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldNextAttemptAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldNextAttemptAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldNextAttemptAt: %w", err) + } + return oldValue.NextAttemptAt, nil +} + +// ClearNextAttemptAt clears the value of the "next_attempt_at" field. +func (m *NotificationOutboxMutation) ClearNextAttemptAt() { + m.next_attempt_at = nil + m.clearedFields[notificationoutbox.FieldNextAttemptAt] = struct{}{} +} + +// NextAttemptAtCleared returns if the "next_attempt_at" field was cleared in this mutation. +func (m *NotificationOutboxMutation) NextAttemptAtCleared() bool { + _, ok := m.clearedFields[notificationoutbox.FieldNextAttemptAt] + return ok +} + +// ResetNextAttemptAt resets all changes to the "next_attempt_at" field. +func (m *NotificationOutboxMutation) ResetNextAttemptAt() { + m.next_attempt_at = nil + delete(m.clearedFields, notificationoutbox.FieldNextAttemptAt) +} + +// SetLockedBy sets the "locked_by" field. +func (m *NotificationOutboxMutation) SetLockedBy(s string) { + m.locked_by = &s +} + +// LockedBy returns the value of the "locked_by" field in the mutation. +func (m *NotificationOutboxMutation) LockedBy() (r string, exists bool) { + v := m.locked_by + if v == nil { + return + } + return *v, true +} + +// OldLockedBy returns the old "locked_by" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldLockedBy(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLockedBy is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLockedBy requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLockedBy: %w", err) + } + return oldValue.LockedBy, nil +} + +// ClearLockedBy clears the value of the "locked_by" field. +func (m *NotificationOutboxMutation) ClearLockedBy() { + m.locked_by = nil + m.clearedFields[notificationoutbox.FieldLockedBy] = struct{}{} +} + +// LockedByCleared returns if the "locked_by" field was cleared in this mutation. +func (m *NotificationOutboxMutation) LockedByCleared() bool { + _, ok := m.clearedFields[notificationoutbox.FieldLockedBy] + return ok +} + +// ResetLockedBy resets all changes to the "locked_by" field. +func (m *NotificationOutboxMutation) ResetLockedBy() { + m.locked_by = nil + delete(m.clearedFields, notificationoutbox.FieldLockedBy) +} + +// SetLockedAt sets the "locked_at" field. +func (m *NotificationOutboxMutation) SetLockedAt(t time.Time) { + m.locked_at = &t +} + +// LockedAt returns the value of the "locked_at" field in the mutation. +func (m *NotificationOutboxMutation) LockedAt() (r time.Time, exists bool) { + v := m.locked_at + if v == nil { + return + } + return *v, true +} + +// OldLockedAt returns the old "locked_at" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldLockedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLockedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLockedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLockedAt: %w", err) + } + return oldValue.LockedAt, nil +} + +// ClearLockedAt clears the value of the "locked_at" field. +func (m *NotificationOutboxMutation) ClearLockedAt() { + m.locked_at = nil + m.clearedFields[notificationoutbox.FieldLockedAt] = struct{}{} +} + +// LockedAtCleared returns if the "locked_at" field was cleared in this mutation. +func (m *NotificationOutboxMutation) LockedAtCleared() bool { + _, ok := m.clearedFields[notificationoutbox.FieldLockedAt] + return ok +} + +// ResetLockedAt resets all changes to the "locked_at" field. +func (m *NotificationOutboxMutation) ResetLockedAt() { + m.locked_at = nil + delete(m.clearedFields, notificationoutbox.FieldLockedAt) +} + +// SetLastError sets the "last_error" field. +func (m *NotificationOutboxMutation) SetLastError(s string) { + m.last_error = &s +} + +// LastError returns the value of the "last_error" field in the mutation. +func (m *NotificationOutboxMutation) LastError() (r string, exists bool) { + v := m.last_error + if v == nil { + return + } + return *v, true +} + +// OldLastError returns the old "last_error" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldLastError(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLastError is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLastError requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLastError: %w", err) + } + return oldValue.LastError, nil +} + +// ClearLastError clears the value of the "last_error" field. +func (m *NotificationOutboxMutation) ClearLastError() { + m.last_error = nil + m.clearedFields[notificationoutbox.FieldLastError] = struct{}{} +} + +// LastErrorCleared returns if the "last_error" field was cleared in this mutation. +func (m *NotificationOutboxMutation) LastErrorCleared() bool { + _, ok := m.clearedFields[notificationoutbox.FieldLastError] + return ok +} + +// ResetLastError resets all changes to the "last_error" field. +func (m *NotificationOutboxMutation) ResetLastError() { + m.last_error = nil + delete(m.clearedFields, notificationoutbox.FieldLastError) +} + +// SetCreatedAt sets the "created_at" field. +func (m *NotificationOutboxMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *NotificationOutboxMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *NotificationOutboxMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *NotificationOutboxMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *NotificationOutboxMutation) UpdatedAt() (r time.Time, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the NotificationOutbox entity. +// If the NotificationOutbox 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 *NotificationOutboxMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *NotificationOutboxMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// ClearIncident clears the "incident" edge to the Incident entity. +func (m *NotificationOutboxMutation) ClearIncident() { + m.clearedincident = true + m.clearedFields[notificationoutbox.FieldIncidentID] = struct{}{} +} + +// IncidentCleared reports if the "incident" edge to the Incident entity was cleared. +func (m *NotificationOutboxMutation) IncidentCleared() bool { + return m.clearedincident +} + +// IncidentIDs returns the "incident" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// IncidentID instead. It exists only for internal usage by the builders. +func (m *NotificationOutboxMutation) IncidentIDs() (ids []int) { + if id := m.incident; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetIncident resets all changes to the "incident" edge. +func (m *NotificationOutboxMutation) ResetIncident() { + m.incident = nil + m.clearedincident = false +} + +// Where appends a list predicates to the NotificationOutboxMutation builder. +func (m *NotificationOutboxMutation) Where(ps ...predicate.NotificationOutbox) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the NotificationOutboxMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *NotificationOutboxMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.NotificationOutbox, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *NotificationOutboxMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *NotificationOutboxMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (NotificationOutbox). +func (m *NotificationOutboxMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *NotificationOutboxMutation) Fields() []string { + fields := make([]string, 0, 14) + if m.kind != nil { + fields = append(fields, notificationoutbox.FieldKind) + } + if m.incident != nil { + fields = append(fields, notificationoutbox.FieldIncidentID) + } + if m.recipient != nil { + fields = append(fields, notificationoutbox.FieldRecipient) + } + if m.payload != nil { + fields = append(fields, notificationoutbox.FieldPayload) + } + if m.change_id != nil { + fields = append(fields, notificationoutbox.FieldChangeID) + } + if m.dedup_key != nil { + fields = append(fields, notificationoutbox.FieldDedupKey) + } + if m.status != nil { + fields = append(fields, notificationoutbox.FieldStatus) + } + if m.attempts != nil { + fields = append(fields, notificationoutbox.FieldAttempts) + } + if m.next_attempt_at != nil { + fields = append(fields, notificationoutbox.FieldNextAttemptAt) + } + if m.locked_by != nil { + fields = append(fields, notificationoutbox.FieldLockedBy) + } + if m.locked_at != nil { + fields = append(fields, notificationoutbox.FieldLockedAt) + } + if m.last_error != nil { + fields = append(fields, notificationoutbox.FieldLastError) + } + if m.created_at != nil { + fields = append(fields, notificationoutbox.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, notificationoutbox.FieldUpdatedAt) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *NotificationOutboxMutation) Field(name string) (ent.Value, bool) { + switch name { + case notificationoutbox.FieldKind: + return m.Kind() + case notificationoutbox.FieldIncidentID: + return m.IncidentID() + case notificationoutbox.FieldRecipient: + return m.Recipient() + case notificationoutbox.FieldPayload: + return m.Payload() + case notificationoutbox.FieldChangeID: + return m.ChangeID() + case notificationoutbox.FieldDedupKey: + return m.DedupKey() + case notificationoutbox.FieldStatus: + return m.Status() + case notificationoutbox.FieldAttempts: + return m.Attempts() + case notificationoutbox.FieldNextAttemptAt: + return m.NextAttemptAt() + case notificationoutbox.FieldLockedBy: + return m.LockedBy() + case notificationoutbox.FieldLockedAt: + return m.LockedAt() + case notificationoutbox.FieldLastError: + return m.LastError() + case notificationoutbox.FieldCreatedAt: + return m.CreatedAt() + case notificationoutbox.FieldUpdatedAt: + return m.UpdatedAt() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *NotificationOutboxMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case notificationoutbox.FieldKind: + return m.OldKind(ctx) + case notificationoutbox.FieldIncidentID: + return m.OldIncidentID(ctx) + case notificationoutbox.FieldRecipient: + return m.OldRecipient(ctx) + case notificationoutbox.FieldPayload: + return m.OldPayload(ctx) + case notificationoutbox.FieldChangeID: + return m.OldChangeID(ctx) + case notificationoutbox.FieldDedupKey: + return m.OldDedupKey(ctx) + case notificationoutbox.FieldStatus: + return m.OldStatus(ctx) + case notificationoutbox.FieldAttempts: + return m.OldAttempts(ctx) + case notificationoutbox.FieldNextAttemptAt: + return m.OldNextAttemptAt(ctx) + case notificationoutbox.FieldLockedBy: + return m.OldLockedBy(ctx) + case notificationoutbox.FieldLockedAt: + return m.OldLockedAt(ctx) + case notificationoutbox.FieldLastError: + return m.OldLastError(ctx) + case notificationoutbox.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case notificationoutbox.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + } + return nil, fmt.Errorf("unknown NotificationOutbox field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *NotificationOutboxMutation) SetField(name string, value ent.Value) error { + switch name { + case notificationoutbox.FieldKind: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetKind(v) + return nil + case notificationoutbox.FieldIncidentID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetIncidentID(v) + return nil + case notificationoutbox.FieldRecipient: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetRecipient(v) + return nil + case notificationoutbox.FieldPayload: + v, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPayload(v) + return nil + case notificationoutbox.FieldChangeID: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetChangeID(v) + return nil + case notificationoutbox.FieldDedupKey: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDedupKey(v) + return nil + case notificationoutbox.FieldStatus: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStatus(v) + return nil + case notificationoutbox.FieldAttempts: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetAttempts(v) + return nil + case notificationoutbox.FieldNextAttemptAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetNextAttemptAt(v) + return nil + case notificationoutbox.FieldLockedBy: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLockedBy(v) + return nil + case notificationoutbox.FieldLockedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLockedAt(v) + return nil + case notificationoutbox.FieldLastError: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLastError(v) + return nil + case notificationoutbox.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case notificationoutbox.FieldUpdatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + } + return fmt.Errorf("unknown NotificationOutbox field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *NotificationOutboxMutation) AddedFields() []string { + var fields []string + if m.addattempts != nil { + fields = append(fields, notificationoutbox.FieldAttempts) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *NotificationOutboxMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case notificationoutbox.FieldAttempts: + return m.AddedAttempts() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *NotificationOutboxMutation) AddField(name string, value ent.Value) error { + switch name { + case notificationoutbox.FieldAttempts: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddAttempts(v) + return nil + } + return fmt.Errorf("unknown NotificationOutbox numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *NotificationOutboxMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(notificationoutbox.FieldNextAttemptAt) { + fields = append(fields, notificationoutbox.FieldNextAttemptAt) + } + if m.FieldCleared(notificationoutbox.FieldLockedBy) { + fields = append(fields, notificationoutbox.FieldLockedBy) + } + if m.FieldCleared(notificationoutbox.FieldLockedAt) { + fields = append(fields, notificationoutbox.FieldLockedAt) + } + if m.FieldCleared(notificationoutbox.FieldLastError) { + fields = append(fields, notificationoutbox.FieldLastError) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *NotificationOutboxMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *NotificationOutboxMutation) ClearField(name string) error { + switch name { + case notificationoutbox.FieldNextAttemptAt: + m.ClearNextAttemptAt() + return nil + case notificationoutbox.FieldLockedBy: + m.ClearLockedBy() + return nil + case notificationoutbox.FieldLockedAt: + m.ClearLockedAt() + return nil + case notificationoutbox.FieldLastError: + m.ClearLastError() + return nil + } + return fmt.Errorf("unknown NotificationOutbox nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *NotificationOutboxMutation) ResetField(name string) error { + switch name { + case notificationoutbox.FieldKind: + m.ResetKind() + return nil + case notificationoutbox.FieldIncidentID: + m.ResetIncidentID() + return nil + case notificationoutbox.FieldRecipient: + m.ResetRecipient() + return nil + case notificationoutbox.FieldPayload: + m.ResetPayload() + return nil + case notificationoutbox.FieldChangeID: + m.ResetChangeID() + return nil + case notificationoutbox.FieldDedupKey: + m.ResetDedupKey() + return nil + case notificationoutbox.FieldStatus: + m.ResetStatus() + return nil + case notificationoutbox.FieldAttempts: + m.ResetAttempts() + return nil + case notificationoutbox.FieldNextAttemptAt: + m.ResetNextAttemptAt() + return nil + case notificationoutbox.FieldLockedBy: + m.ResetLockedBy() + return nil + case notificationoutbox.FieldLockedAt: + m.ResetLockedAt() + return nil + case notificationoutbox.FieldLastError: + m.ResetLastError() + return nil + case notificationoutbox.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case notificationoutbox.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + } + return fmt.Errorf("unknown NotificationOutbox field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *NotificationOutboxMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.incident != nil { + edges = append(edges, notificationoutbox.EdgeIncident) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *NotificationOutboxMutation) AddedIDs(name string) []ent.Value { + switch name { + case notificationoutbox.EdgeIncident: + if id := m.incident; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *NotificationOutboxMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *NotificationOutboxMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *NotificationOutboxMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedincident { + edges = append(edges, notificationoutbox.EdgeIncident) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *NotificationOutboxMutation) EdgeCleared(name string) bool { + switch name { + case notificationoutbox.EdgeIncident: + return m.clearedincident + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *NotificationOutboxMutation) ClearEdge(name string) error { + switch name { + case notificationoutbox.EdgeIncident: + m.ClearIncident() + return nil + } + return fmt.Errorf("unknown NotificationOutbox unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *NotificationOutboxMutation) ResetEdge(name string) error { + switch name { + case notificationoutbox.EdgeIncident: + m.ResetIncident() + return nil + } + return fmt.Errorf("unknown NotificationOutbox edge %s", name) +} diff --git a/ent/notificationoutbox.go b/ent/notificationoutbox.go new file mode 100644 index 0000000..b34cf51 --- /dev/null +++ b/ent/notificationoutbox.go @@ -0,0 +1,283 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" +) + +// NotificationOutbox is the model entity for the NotificationOutbox schema. +type NotificationOutbox struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Kind holds the value of the "kind" field. + Kind string `json:"kind,omitempty"` + // IncidentID holds the value of the "incident_id" field. + IncidentID int `json:"incident_id,omitempty"` + // Recipient holds the value of the "recipient" field. + Recipient string `json:"recipient,omitempty"` + // Payload holds the value of the "payload" field. + Payload map[string]interface{} `json:"payload,omitempty"` + // ChangeID holds the value of the "change_id" field. + ChangeID string `json:"change_id,omitempty"` + // DedupKey holds the value of the "dedup_key" field. + DedupKey string `json:"dedup_key,omitempty"` + // Status holds the value of the "status" field. + Status string `json:"status,omitempty"` + // Attempts holds the value of the "attempts" field. + Attempts int `json:"attempts,omitempty"` + // NextAttemptAt holds the value of the "next_attempt_at" field. + NextAttemptAt time.Time `json:"next_attempt_at,omitempty"` + // LockedBy holds the value of the "locked_by" field. + LockedBy string `json:"locked_by,omitempty"` + // LockedAt holds the value of the "locked_at" field. + LockedAt time.Time `json:"locked_at,omitempty"` + // LastError holds the value of the "last_error" field. + LastError string `json:"last_error,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt time.Time `json:"updated_at,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the NotificationOutboxQuery when eager-loading is set. + Edges NotificationOutboxEdges `json:"edges"` + selectValues sql.SelectValues +} + +// NotificationOutboxEdges holds the relations/edges for other nodes in the graph. +type NotificationOutboxEdges struct { + // Incident holds the value of the incident edge. + Incident *Incident `json:"incident,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// IncidentOrErr returns the Incident value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e NotificationOutboxEdges) IncidentOrErr() (*Incident, error) { + if e.Incident != nil { + return e.Incident, nil + } else if e.loadedTypes[0] { + return nil, &NotFoundError{label: incident.Label} + } + return nil, &NotLoadedError{edge: "incident"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*NotificationOutbox) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case notificationoutbox.FieldPayload: + values[i] = new([]byte) + case notificationoutbox.FieldID, notificationoutbox.FieldIncidentID, notificationoutbox.FieldAttempts: + values[i] = new(sql.NullInt64) + case notificationoutbox.FieldKind, notificationoutbox.FieldRecipient, notificationoutbox.FieldChangeID, notificationoutbox.FieldDedupKey, notificationoutbox.FieldStatus, notificationoutbox.FieldLockedBy, notificationoutbox.FieldLastError: + values[i] = new(sql.NullString) + case notificationoutbox.FieldNextAttemptAt, notificationoutbox.FieldLockedAt, notificationoutbox.FieldCreatedAt, notificationoutbox.FieldUpdatedAt: + values[i] = new(sql.NullTime) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the NotificationOutbox fields. +func (_m *NotificationOutbox) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case notificationoutbox.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + _m.ID = int(value.Int64) + case notificationoutbox.FieldKind: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field kind", values[i]) + } else if value.Valid { + _m.Kind = value.String + } + case notificationoutbox.FieldIncidentID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field incident_id", values[i]) + } else if value.Valid { + _m.IncidentID = int(value.Int64) + } + case notificationoutbox.FieldRecipient: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field recipient", values[i]) + } else if value.Valid { + _m.Recipient = value.String + } + case notificationoutbox.FieldPayload: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field payload", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &_m.Payload); err != nil { + return fmt.Errorf("unmarshal field payload: %w", err) + } + } + case notificationoutbox.FieldChangeID: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field change_id", values[i]) + } else if value.Valid { + _m.ChangeID = value.String + } + case notificationoutbox.FieldDedupKey: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field dedup_key", values[i]) + } else if value.Valid { + _m.DedupKey = value.String + } + case notificationoutbox.FieldStatus: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field status", values[i]) + } else if value.Valid { + _m.Status = value.String + } + case notificationoutbox.FieldAttempts: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field attempts", values[i]) + } else if value.Valid { + _m.Attempts = int(value.Int64) + } + case notificationoutbox.FieldNextAttemptAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field next_attempt_at", values[i]) + } else if value.Valid { + _m.NextAttemptAt = value.Time + } + case notificationoutbox.FieldLockedBy: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field locked_by", values[i]) + } else if value.Valid { + _m.LockedBy = value.String + } + case notificationoutbox.FieldLockedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field locked_at", values[i]) + } else if value.Valid { + _m.LockedAt = value.Time + } + case notificationoutbox.FieldLastError: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field last_error", values[i]) + } else if value.Valid { + _m.LastError = value.String + } + case notificationoutbox.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + _m.CreatedAt = value.Time + } + case notificationoutbox.FieldUpdatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value.Valid { + _m.UpdatedAt = value.Time + } + default: + _m.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the NotificationOutbox. +// This includes values selected through modifiers, order, etc. +func (_m *NotificationOutbox) Value(name string) (ent.Value, error) { + return _m.selectValues.Get(name) +} + +// QueryIncident queries the "incident" edge of the NotificationOutbox entity. +func (_m *NotificationOutbox) QueryIncident() *IncidentQuery { + return NewNotificationOutboxClient(_m.config).QueryIncident(_m) +} + +// Update returns a builder for updating this NotificationOutbox. +// Note that you need to call NotificationOutbox.Unwrap() before calling this method if this NotificationOutbox +// was returned from a transaction, and the transaction was committed or rolled back. +func (_m *NotificationOutbox) Update() *NotificationOutboxUpdateOne { + return NewNotificationOutboxClient(_m.config).UpdateOne(_m) +} + +// Unwrap unwraps the NotificationOutbox entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (_m *NotificationOutbox) Unwrap() *NotificationOutbox { + _tx, ok := _m.config.driver.(*txDriver) + if !ok { + panic("ent: NotificationOutbox is not a transactional entity") + } + _m.config.driver = _tx.drv + return _m +} + +// String implements the fmt.Stringer. +func (_m *NotificationOutbox) String() string { + var builder strings.Builder + builder.WriteString("NotificationOutbox(") + builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID)) + builder.WriteString("kind=") + builder.WriteString(_m.Kind) + builder.WriteString(", ") + builder.WriteString("incident_id=") + builder.WriteString(fmt.Sprintf("%v", _m.IncidentID)) + builder.WriteString(", ") + builder.WriteString("recipient=") + builder.WriteString(_m.Recipient) + builder.WriteString(", ") + builder.WriteString("payload=") + builder.WriteString(fmt.Sprintf("%v", _m.Payload)) + builder.WriteString(", ") + builder.WriteString("change_id=") + builder.WriteString(_m.ChangeID) + builder.WriteString(", ") + builder.WriteString("dedup_key=") + builder.WriteString(_m.DedupKey) + builder.WriteString(", ") + builder.WriteString("status=") + builder.WriteString(_m.Status) + builder.WriteString(", ") + builder.WriteString("attempts=") + builder.WriteString(fmt.Sprintf("%v", _m.Attempts)) + builder.WriteString(", ") + builder.WriteString("next_attempt_at=") + builder.WriteString(_m.NextAttemptAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("locked_by=") + builder.WriteString(_m.LockedBy) + builder.WriteString(", ") + builder.WriteString("locked_at=") + builder.WriteString(_m.LockedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("last_error=") + builder.WriteString(_m.LastError) + builder.WriteString(", ") + builder.WriteString("created_at=") + builder.WriteString(_m.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(_m.UpdatedAt.Format(time.ANSIC)) + builder.WriteByte(')') + return builder.String() +} + +// NotificationOutboxes is a parsable slice of NotificationOutbox. +type NotificationOutboxes []*NotificationOutbox diff --git a/ent/notificationoutbox/notificationoutbox.go b/ent/notificationoutbox/notificationoutbox.go new file mode 100644 index 0000000..a52f974 --- /dev/null +++ b/ent/notificationoutbox/notificationoutbox.go @@ -0,0 +1,185 @@ +// Code generated by ent, DO NOT EDIT. + +package notificationoutbox + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the notificationoutbox type in the database. + Label = "notification_outbox" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldKind holds the string denoting the kind field in the database. + FieldKind = "kind" + // FieldIncidentID holds the string denoting the incident_id field in the database. + FieldIncidentID = "incident_id" + // FieldRecipient holds the string denoting the recipient field in the database. + FieldRecipient = "recipient" + // FieldPayload holds the string denoting the payload field in the database. + FieldPayload = "payload" + // FieldChangeID holds the string denoting the change_id field in the database. + FieldChangeID = "change_id" + // FieldDedupKey holds the string denoting the dedup_key field in the database. + FieldDedupKey = "dedup_key" + // FieldStatus holds the string denoting the status field in the database. + FieldStatus = "status" + // FieldAttempts holds the string denoting the attempts field in the database. + FieldAttempts = "attempts" + // FieldNextAttemptAt holds the string denoting the next_attempt_at field in the database. + FieldNextAttemptAt = "next_attempt_at" + // FieldLockedBy holds the string denoting the locked_by field in the database. + FieldLockedBy = "locked_by" + // FieldLockedAt holds the string denoting the locked_at field in the database. + FieldLockedAt = "locked_at" + // FieldLastError holds the string denoting the last_error field in the database. + FieldLastError = "last_error" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // EdgeIncident holds the string denoting the incident edge name in mutations. + EdgeIncident = "incident" + // Table holds the table name of the notificationoutbox in the database. + Table = "notification_outbox" + // IncidentTable is the table that holds the incident relation/edge. + IncidentTable = "notification_outbox" + // IncidentInverseTable is the table name for the Incident entity. + // It exists in this package in order to avoid circular dependency with the "incident" package. + IncidentInverseTable = "incident" + // IncidentColumn is the table column denoting the incident relation/edge. + IncidentColumn = "incident_id" +) + +// Columns holds all SQL columns for notificationoutbox fields. +var Columns = []string{ + FieldID, + FieldKind, + FieldIncidentID, + FieldRecipient, + FieldPayload, + FieldChangeID, + FieldDedupKey, + FieldStatus, + FieldAttempts, + FieldNextAttemptAt, + FieldLockedBy, + FieldLockedAt, + FieldLastError, + FieldCreatedAt, + FieldUpdatedAt, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // KindValidator is a validator for the "kind" field. It is called by the builders before save. + KindValidator func(string) error + // RecipientValidator is a validator for the "recipient" field. It is called by the builders before save. + RecipientValidator func(string) error + // ChangeIDValidator is a validator for the "change_id" field. It is called by the builders before save. + ChangeIDValidator func(string) error + // DedupKeyValidator is a validator for the "dedup_key" field. It is called by the builders before save. + DedupKeyValidator func(string) error + // DefaultStatus holds the default value on creation for the "status" field. + DefaultStatus string + // DefaultAttempts holds the default value on creation for the "attempts" field. + DefaultAttempts int +) + +// OrderOption defines the ordering options for the NotificationOutbox queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByKind orders the results by the kind field. +func ByKind(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldKind, opts...).ToFunc() +} + +// ByIncidentID orders the results by the incident_id field. +func ByIncidentID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldIncidentID, opts...).ToFunc() +} + +// ByRecipient orders the results by the recipient field. +func ByRecipient(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldRecipient, opts...).ToFunc() +} + +// ByChangeID orders the results by the change_id field. +func ByChangeID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldChangeID, opts...).ToFunc() +} + +// ByDedupKey orders the results by the dedup_key field. +func ByDedupKey(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDedupKey, opts...).ToFunc() +} + +// ByStatus orders the results by the status field. +func ByStatus(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldStatus, opts...).ToFunc() +} + +// ByAttempts orders the results by the attempts field. +func ByAttempts(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldAttempts, opts...).ToFunc() +} + +// ByNextAttemptAt orders the results by the next_attempt_at field. +func ByNextAttemptAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldNextAttemptAt, opts...).ToFunc() +} + +// ByLockedBy orders the results by the locked_by field. +func ByLockedBy(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLockedBy, opts...).ToFunc() +} + +// ByLockedAt orders the results by the locked_at field. +func ByLockedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLockedAt, opts...).ToFunc() +} + +// ByLastError orders the results by the last_error field. +func ByLastError(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLastError, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// ByIncidentField orders the results by incident field. +func ByIncidentField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newIncidentStep(), sql.OrderByField(field, opts...)) + } +} +func newIncidentStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(IncidentInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, IncidentTable, IncidentColumn), + ) +} diff --git a/ent/notificationoutbox/where.go b/ent/notificationoutbox/where.go new file mode 100644 index 0000000..325eb9b --- /dev/null +++ b/ent/notificationoutbox/where.go @@ -0,0 +1,874 @@ +// Code generated by ent, DO NOT EDIT. + +package notificationoutbox + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldID, id)) +} + +// Kind applies equality check predicate on the "kind" field. It's identical to KindEQ. +func Kind(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldKind, v)) +} + +// IncidentID applies equality check predicate on the "incident_id" field. It's identical to IncidentIDEQ. +func IncidentID(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldIncidentID, v)) +} + +// Recipient applies equality check predicate on the "recipient" field. It's identical to RecipientEQ. +func Recipient(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldRecipient, v)) +} + +// ChangeID applies equality check predicate on the "change_id" field. It's identical to ChangeIDEQ. +func ChangeID(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldChangeID, v)) +} + +// DedupKey applies equality check predicate on the "dedup_key" field. It's identical to DedupKeyEQ. +func DedupKey(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldDedupKey, v)) +} + +// Status applies equality check predicate on the "status" field. It's identical to StatusEQ. +func Status(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldStatus, v)) +} + +// Attempts applies equality check predicate on the "attempts" field. It's identical to AttemptsEQ. +func Attempts(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldAttempts, v)) +} + +// NextAttemptAt applies equality check predicate on the "next_attempt_at" field. It's identical to NextAttemptAtEQ. +func NextAttemptAt(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldNextAttemptAt, v)) +} + +// LockedBy applies equality check predicate on the "locked_by" field. It's identical to LockedByEQ. +func LockedBy(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldLockedBy, v)) +} + +// LockedAt applies equality check predicate on the "locked_at" field. It's identical to LockedAtEQ. +func LockedAt(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldLockedAt, v)) +} + +// LastError applies equality check predicate on the "last_error" field. It's identical to LastErrorEQ. +func LastError(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldLastError, v)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldCreatedAt, v)) +} + +// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ. +func UpdatedAt(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// KindEQ applies the EQ predicate on the "kind" field. +func KindEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldKind, v)) +} + +// KindNEQ applies the NEQ predicate on the "kind" field. +func KindNEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldKind, v)) +} + +// KindIn applies the In predicate on the "kind" field. +func KindIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldKind, vs...)) +} + +// KindNotIn applies the NotIn predicate on the "kind" field. +func KindNotIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldKind, vs...)) +} + +// KindGT applies the GT predicate on the "kind" field. +func KindGT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldKind, v)) +} + +// KindGTE applies the GTE predicate on the "kind" field. +func KindGTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldKind, v)) +} + +// KindLT applies the LT predicate on the "kind" field. +func KindLT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldKind, v)) +} + +// KindLTE applies the LTE predicate on the "kind" field. +func KindLTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldKind, v)) +} + +// KindContains applies the Contains predicate on the "kind" field. +func KindContains(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContains(FieldKind, v)) +} + +// KindHasPrefix applies the HasPrefix predicate on the "kind" field. +func KindHasPrefix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasPrefix(FieldKind, v)) +} + +// KindHasSuffix applies the HasSuffix predicate on the "kind" field. +func KindHasSuffix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasSuffix(FieldKind, v)) +} + +// KindEqualFold applies the EqualFold predicate on the "kind" field. +func KindEqualFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEqualFold(FieldKind, v)) +} + +// KindContainsFold applies the ContainsFold predicate on the "kind" field. +func KindContainsFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContainsFold(FieldKind, v)) +} + +// IncidentIDEQ applies the EQ predicate on the "incident_id" field. +func IncidentIDEQ(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldIncidentID, v)) +} + +// IncidentIDNEQ applies the NEQ predicate on the "incident_id" field. +func IncidentIDNEQ(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldIncidentID, v)) +} + +// IncidentIDIn applies the In predicate on the "incident_id" field. +func IncidentIDIn(vs ...int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldIncidentID, vs...)) +} + +// IncidentIDNotIn applies the NotIn predicate on the "incident_id" field. +func IncidentIDNotIn(vs ...int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldIncidentID, vs...)) +} + +// RecipientEQ applies the EQ predicate on the "recipient" field. +func RecipientEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldRecipient, v)) +} + +// RecipientNEQ applies the NEQ predicate on the "recipient" field. +func RecipientNEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldRecipient, v)) +} + +// RecipientIn applies the In predicate on the "recipient" field. +func RecipientIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldRecipient, vs...)) +} + +// RecipientNotIn applies the NotIn predicate on the "recipient" field. +func RecipientNotIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldRecipient, vs...)) +} + +// RecipientGT applies the GT predicate on the "recipient" field. +func RecipientGT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldRecipient, v)) +} + +// RecipientGTE applies the GTE predicate on the "recipient" field. +func RecipientGTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldRecipient, v)) +} + +// RecipientLT applies the LT predicate on the "recipient" field. +func RecipientLT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldRecipient, v)) +} + +// RecipientLTE applies the LTE predicate on the "recipient" field. +func RecipientLTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldRecipient, v)) +} + +// RecipientContains applies the Contains predicate on the "recipient" field. +func RecipientContains(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContains(FieldRecipient, v)) +} + +// RecipientHasPrefix applies the HasPrefix predicate on the "recipient" field. +func RecipientHasPrefix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasPrefix(FieldRecipient, v)) +} + +// RecipientHasSuffix applies the HasSuffix predicate on the "recipient" field. +func RecipientHasSuffix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasSuffix(FieldRecipient, v)) +} + +// RecipientEqualFold applies the EqualFold predicate on the "recipient" field. +func RecipientEqualFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEqualFold(FieldRecipient, v)) +} + +// RecipientContainsFold applies the ContainsFold predicate on the "recipient" field. +func RecipientContainsFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContainsFold(FieldRecipient, v)) +} + +// ChangeIDEQ applies the EQ predicate on the "change_id" field. +func ChangeIDEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldChangeID, v)) +} + +// ChangeIDNEQ applies the NEQ predicate on the "change_id" field. +func ChangeIDNEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldChangeID, v)) +} + +// ChangeIDIn applies the In predicate on the "change_id" field. +func ChangeIDIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldChangeID, vs...)) +} + +// ChangeIDNotIn applies the NotIn predicate on the "change_id" field. +func ChangeIDNotIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldChangeID, vs...)) +} + +// ChangeIDGT applies the GT predicate on the "change_id" field. +func ChangeIDGT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldChangeID, v)) +} + +// ChangeIDGTE applies the GTE predicate on the "change_id" field. +func ChangeIDGTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldChangeID, v)) +} + +// ChangeIDLT applies the LT predicate on the "change_id" field. +func ChangeIDLT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldChangeID, v)) +} + +// ChangeIDLTE applies the LTE predicate on the "change_id" field. +func ChangeIDLTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldChangeID, v)) +} + +// ChangeIDContains applies the Contains predicate on the "change_id" field. +func ChangeIDContains(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContains(FieldChangeID, v)) +} + +// ChangeIDHasPrefix applies the HasPrefix predicate on the "change_id" field. +func ChangeIDHasPrefix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasPrefix(FieldChangeID, v)) +} + +// ChangeIDHasSuffix applies the HasSuffix predicate on the "change_id" field. +func ChangeIDHasSuffix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasSuffix(FieldChangeID, v)) +} + +// ChangeIDEqualFold applies the EqualFold predicate on the "change_id" field. +func ChangeIDEqualFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEqualFold(FieldChangeID, v)) +} + +// ChangeIDContainsFold applies the ContainsFold predicate on the "change_id" field. +func ChangeIDContainsFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContainsFold(FieldChangeID, v)) +} + +// DedupKeyEQ applies the EQ predicate on the "dedup_key" field. +func DedupKeyEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldDedupKey, v)) +} + +// DedupKeyNEQ applies the NEQ predicate on the "dedup_key" field. +func DedupKeyNEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldDedupKey, v)) +} + +// DedupKeyIn applies the In predicate on the "dedup_key" field. +func DedupKeyIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldDedupKey, vs...)) +} + +// DedupKeyNotIn applies the NotIn predicate on the "dedup_key" field. +func DedupKeyNotIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldDedupKey, vs...)) +} + +// DedupKeyGT applies the GT predicate on the "dedup_key" field. +func DedupKeyGT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldDedupKey, v)) +} + +// DedupKeyGTE applies the GTE predicate on the "dedup_key" field. +func DedupKeyGTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldDedupKey, v)) +} + +// DedupKeyLT applies the LT predicate on the "dedup_key" field. +func DedupKeyLT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldDedupKey, v)) +} + +// DedupKeyLTE applies the LTE predicate on the "dedup_key" field. +func DedupKeyLTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldDedupKey, v)) +} + +// DedupKeyContains applies the Contains predicate on the "dedup_key" field. +func DedupKeyContains(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContains(FieldDedupKey, v)) +} + +// DedupKeyHasPrefix applies the HasPrefix predicate on the "dedup_key" field. +func DedupKeyHasPrefix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasPrefix(FieldDedupKey, v)) +} + +// DedupKeyHasSuffix applies the HasSuffix predicate on the "dedup_key" field. +func DedupKeyHasSuffix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasSuffix(FieldDedupKey, v)) +} + +// DedupKeyEqualFold applies the EqualFold predicate on the "dedup_key" field. +func DedupKeyEqualFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEqualFold(FieldDedupKey, v)) +} + +// DedupKeyContainsFold applies the ContainsFold predicate on the "dedup_key" field. +func DedupKeyContainsFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContainsFold(FieldDedupKey, v)) +} + +// StatusEQ applies the EQ predicate on the "status" field. +func StatusEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldStatus, v)) +} + +// StatusNEQ applies the NEQ predicate on the "status" field. +func StatusNEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldStatus, v)) +} + +// StatusIn applies the In predicate on the "status" field. +func StatusIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldStatus, vs...)) +} + +// StatusNotIn applies the NotIn predicate on the "status" field. +func StatusNotIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldStatus, vs...)) +} + +// StatusGT applies the GT predicate on the "status" field. +func StatusGT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldStatus, v)) +} + +// StatusGTE applies the GTE predicate on the "status" field. +func StatusGTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldStatus, v)) +} + +// StatusLT applies the LT predicate on the "status" field. +func StatusLT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldStatus, v)) +} + +// StatusLTE applies the LTE predicate on the "status" field. +func StatusLTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldStatus, v)) +} + +// StatusContains applies the Contains predicate on the "status" field. +func StatusContains(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContains(FieldStatus, v)) +} + +// StatusHasPrefix applies the HasPrefix predicate on the "status" field. +func StatusHasPrefix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasPrefix(FieldStatus, v)) +} + +// StatusHasSuffix applies the HasSuffix predicate on the "status" field. +func StatusHasSuffix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasSuffix(FieldStatus, v)) +} + +// StatusEqualFold applies the EqualFold predicate on the "status" field. +func StatusEqualFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEqualFold(FieldStatus, v)) +} + +// StatusContainsFold applies the ContainsFold predicate on the "status" field. +func StatusContainsFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContainsFold(FieldStatus, v)) +} + +// AttemptsEQ applies the EQ predicate on the "attempts" field. +func AttemptsEQ(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldAttempts, v)) +} + +// AttemptsNEQ applies the NEQ predicate on the "attempts" field. +func AttemptsNEQ(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldAttempts, v)) +} + +// AttemptsIn applies the In predicate on the "attempts" field. +func AttemptsIn(vs ...int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldAttempts, vs...)) +} + +// AttemptsNotIn applies the NotIn predicate on the "attempts" field. +func AttemptsNotIn(vs ...int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldAttempts, vs...)) +} + +// AttemptsGT applies the GT predicate on the "attempts" field. +func AttemptsGT(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldAttempts, v)) +} + +// AttemptsGTE applies the GTE predicate on the "attempts" field. +func AttemptsGTE(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldAttempts, v)) +} + +// AttemptsLT applies the LT predicate on the "attempts" field. +func AttemptsLT(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldAttempts, v)) +} + +// AttemptsLTE applies the LTE predicate on the "attempts" field. +func AttemptsLTE(v int) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldAttempts, v)) +} + +// NextAttemptAtEQ applies the EQ predicate on the "next_attempt_at" field. +func NextAttemptAtEQ(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldNextAttemptAt, v)) +} + +// NextAttemptAtNEQ applies the NEQ predicate on the "next_attempt_at" field. +func NextAttemptAtNEQ(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldNextAttemptAt, v)) +} + +// NextAttemptAtIn applies the In predicate on the "next_attempt_at" field. +func NextAttemptAtIn(vs ...time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldNextAttemptAt, vs...)) +} + +// NextAttemptAtNotIn applies the NotIn predicate on the "next_attempt_at" field. +func NextAttemptAtNotIn(vs ...time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldNextAttemptAt, vs...)) +} + +// NextAttemptAtGT applies the GT predicate on the "next_attempt_at" field. +func NextAttemptAtGT(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldNextAttemptAt, v)) +} + +// NextAttemptAtGTE applies the GTE predicate on the "next_attempt_at" field. +func NextAttemptAtGTE(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldNextAttemptAt, v)) +} + +// NextAttemptAtLT applies the LT predicate on the "next_attempt_at" field. +func NextAttemptAtLT(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldNextAttemptAt, v)) +} + +// NextAttemptAtLTE applies the LTE predicate on the "next_attempt_at" field. +func NextAttemptAtLTE(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldNextAttemptAt, v)) +} + +// NextAttemptAtIsNil applies the IsNil predicate on the "next_attempt_at" field. +func NextAttemptAtIsNil() predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIsNull(FieldNextAttemptAt)) +} + +// NextAttemptAtNotNil applies the NotNil predicate on the "next_attempt_at" field. +func NextAttemptAtNotNil() predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotNull(FieldNextAttemptAt)) +} + +// LockedByEQ applies the EQ predicate on the "locked_by" field. +func LockedByEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldLockedBy, v)) +} + +// LockedByNEQ applies the NEQ predicate on the "locked_by" field. +func LockedByNEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldLockedBy, v)) +} + +// LockedByIn applies the In predicate on the "locked_by" field. +func LockedByIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldLockedBy, vs...)) +} + +// LockedByNotIn applies the NotIn predicate on the "locked_by" field. +func LockedByNotIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldLockedBy, vs...)) +} + +// LockedByGT applies the GT predicate on the "locked_by" field. +func LockedByGT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldLockedBy, v)) +} + +// LockedByGTE applies the GTE predicate on the "locked_by" field. +func LockedByGTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldLockedBy, v)) +} + +// LockedByLT applies the LT predicate on the "locked_by" field. +func LockedByLT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldLockedBy, v)) +} + +// LockedByLTE applies the LTE predicate on the "locked_by" field. +func LockedByLTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldLockedBy, v)) +} + +// LockedByContains applies the Contains predicate on the "locked_by" field. +func LockedByContains(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContains(FieldLockedBy, v)) +} + +// LockedByHasPrefix applies the HasPrefix predicate on the "locked_by" field. +func LockedByHasPrefix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasPrefix(FieldLockedBy, v)) +} + +// LockedByHasSuffix applies the HasSuffix predicate on the "locked_by" field. +func LockedByHasSuffix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasSuffix(FieldLockedBy, v)) +} + +// LockedByIsNil applies the IsNil predicate on the "locked_by" field. +func LockedByIsNil() predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIsNull(FieldLockedBy)) +} + +// LockedByNotNil applies the NotNil predicate on the "locked_by" field. +func LockedByNotNil() predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotNull(FieldLockedBy)) +} + +// LockedByEqualFold applies the EqualFold predicate on the "locked_by" field. +func LockedByEqualFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEqualFold(FieldLockedBy, v)) +} + +// LockedByContainsFold applies the ContainsFold predicate on the "locked_by" field. +func LockedByContainsFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContainsFold(FieldLockedBy, v)) +} + +// LockedAtEQ applies the EQ predicate on the "locked_at" field. +func LockedAtEQ(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldLockedAt, v)) +} + +// LockedAtNEQ applies the NEQ predicate on the "locked_at" field. +func LockedAtNEQ(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldLockedAt, v)) +} + +// LockedAtIn applies the In predicate on the "locked_at" field. +func LockedAtIn(vs ...time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldLockedAt, vs...)) +} + +// LockedAtNotIn applies the NotIn predicate on the "locked_at" field. +func LockedAtNotIn(vs ...time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldLockedAt, vs...)) +} + +// LockedAtGT applies the GT predicate on the "locked_at" field. +func LockedAtGT(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldLockedAt, v)) +} + +// LockedAtGTE applies the GTE predicate on the "locked_at" field. +func LockedAtGTE(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldLockedAt, v)) +} + +// LockedAtLT applies the LT predicate on the "locked_at" field. +func LockedAtLT(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldLockedAt, v)) +} + +// LockedAtLTE applies the LTE predicate on the "locked_at" field. +func LockedAtLTE(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldLockedAt, v)) +} + +// LockedAtIsNil applies the IsNil predicate on the "locked_at" field. +func LockedAtIsNil() predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIsNull(FieldLockedAt)) +} + +// LockedAtNotNil applies the NotNil predicate on the "locked_at" field. +func LockedAtNotNil() predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotNull(FieldLockedAt)) +} + +// LastErrorEQ applies the EQ predicate on the "last_error" field. +func LastErrorEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldLastError, v)) +} + +// LastErrorNEQ applies the NEQ predicate on the "last_error" field. +func LastErrorNEQ(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldLastError, v)) +} + +// LastErrorIn applies the In predicate on the "last_error" field. +func LastErrorIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldLastError, vs...)) +} + +// LastErrorNotIn applies the NotIn predicate on the "last_error" field. +func LastErrorNotIn(vs ...string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldLastError, vs...)) +} + +// LastErrorGT applies the GT predicate on the "last_error" field. +func LastErrorGT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldLastError, v)) +} + +// LastErrorGTE applies the GTE predicate on the "last_error" field. +func LastErrorGTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldLastError, v)) +} + +// LastErrorLT applies the LT predicate on the "last_error" field. +func LastErrorLT(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldLastError, v)) +} + +// LastErrorLTE applies the LTE predicate on the "last_error" field. +func LastErrorLTE(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldLastError, v)) +} + +// LastErrorContains applies the Contains predicate on the "last_error" field. +func LastErrorContains(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContains(FieldLastError, v)) +} + +// LastErrorHasPrefix applies the HasPrefix predicate on the "last_error" field. +func LastErrorHasPrefix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasPrefix(FieldLastError, v)) +} + +// LastErrorHasSuffix applies the HasSuffix predicate on the "last_error" field. +func LastErrorHasSuffix(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldHasSuffix(FieldLastError, v)) +} + +// LastErrorIsNil applies the IsNil predicate on the "last_error" field. +func LastErrorIsNil() predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIsNull(FieldLastError)) +} + +// LastErrorNotNil applies the NotNil predicate on the "last_error" field. +func LastErrorNotNil() predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotNull(FieldLastError)) +} + +// LastErrorEqualFold applies the EqualFold predicate on the "last_error" field. +func LastErrorEqualFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEqualFold(FieldLastError, v)) +} + +// LastErrorContainsFold applies the ContainsFold predicate on the "last_error" field. +func LastErrorContainsFold(v string) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldContainsFold(FieldLastError, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// HasIncident applies the HasEdge predicate on the "incident" edge. +func HasIncident() predicate.NotificationOutbox { + return predicate.NotificationOutbox(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, IncidentTable, IncidentColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasIncidentWith applies the HasEdge predicate on the "incident" edge with a given conditions (other predicates). +func HasIncidentWith(preds ...predicate.Incident) predicate.NotificationOutbox { + return predicate.NotificationOutbox(func(s *sql.Selector) { + step := newIncidentStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.NotificationOutbox) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.NotificationOutbox) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.NotificationOutbox) predicate.NotificationOutbox { + return predicate.NotificationOutbox(sql.NotPredicates(p)) +} diff --git a/ent/notificationoutbox_create.go b/ent/notificationoutbox_create.go new file mode 100644 index 0000000..6963ca4 --- /dev/null +++ b/ent/notificationoutbox_create.go @@ -0,0 +1,1360 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" +) + +// NotificationOutboxCreate is the builder for creating a NotificationOutbox entity. +type NotificationOutboxCreate struct { + config + mutation *NotificationOutboxMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetKind sets the "kind" field. +func (_c *NotificationOutboxCreate) SetKind(v string) *NotificationOutboxCreate { + _c.mutation.SetKind(v) + return _c +} + +// SetIncidentID sets the "incident_id" field. +func (_c *NotificationOutboxCreate) SetIncidentID(v int) *NotificationOutboxCreate { + _c.mutation.SetIncidentID(v) + return _c +} + +// SetRecipient sets the "recipient" field. +func (_c *NotificationOutboxCreate) SetRecipient(v string) *NotificationOutboxCreate { + _c.mutation.SetRecipient(v) + return _c +} + +// SetPayload sets the "payload" field. +func (_c *NotificationOutboxCreate) SetPayload(v map[string]interface{}) *NotificationOutboxCreate { + _c.mutation.SetPayload(v) + return _c +} + +// SetChangeID sets the "change_id" field. +func (_c *NotificationOutboxCreate) SetChangeID(v string) *NotificationOutboxCreate { + _c.mutation.SetChangeID(v) + return _c +} + +// SetDedupKey sets the "dedup_key" field. +func (_c *NotificationOutboxCreate) SetDedupKey(v string) *NotificationOutboxCreate { + _c.mutation.SetDedupKey(v) + return _c +} + +// SetStatus sets the "status" field. +func (_c *NotificationOutboxCreate) SetStatus(v string) *NotificationOutboxCreate { + _c.mutation.SetStatus(v) + return _c +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (_c *NotificationOutboxCreate) SetNillableStatus(v *string) *NotificationOutboxCreate { + if v != nil { + _c.SetStatus(*v) + } + return _c +} + +// SetAttempts sets the "attempts" field. +func (_c *NotificationOutboxCreate) SetAttempts(v int) *NotificationOutboxCreate { + _c.mutation.SetAttempts(v) + return _c +} + +// SetNillableAttempts sets the "attempts" field if the given value is not nil. +func (_c *NotificationOutboxCreate) SetNillableAttempts(v *int) *NotificationOutboxCreate { + if v != nil { + _c.SetAttempts(*v) + } + return _c +} + +// SetNextAttemptAt sets the "next_attempt_at" field. +func (_c *NotificationOutboxCreate) SetNextAttemptAt(v time.Time) *NotificationOutboxCreate { + _c.mutation.SetNextAttemptAt(v) + return _c +} + +// SetNillableNextAttemptAt sets the "next_attempt_at" field if the given value is not nil. +func (_c *NotificationOutboxCreate) SetNillableNextAttemptAt(v *time.Time) *NotificationOutboxCreate { + if v != nil { + _c.SetNextAttemptAt(*v) + } + return _c +} + +// SetLockedBy sets the "locked_by" field. +func (_c *NotificationOutboxCreate) SetLockedBy(v string) *NotificationOutboxCreate { + _c.mutation.SetLockedBy(v) + return _c +} + +// SetNillableLockedBy sets the "locked_by" field if the given value is not nil. +func (_c *NotificationOutboxCreate) SetNillableLockedBy(v *string) *NotificationOutboxCreate { + if v != nil { + _c.SetLockedBy(*v) + } + return _c +} + +// SetLockedAt sets the "locked_at" field. +func (_c *NotificationOutboxCreate) SetLockedAt(v time.Time) *NotificationOutboxCreate { + _c.mutation.SetLockedAt(v) + return _c +} + +// SetNillableLockedAt sets the "locked_at" field if the given value is not nil. +func (_c *NotificationOutboxCreate) SetNillableLockedAt(v *time.Time) *NotificationOutboxCreate { + if v != nil { + _c.SetLockedAt(*v) + } + return _c +} + +// SetLastError sets the "last_error" field. +func (_c *NotificationOutboxCreate) SetLastError(v string) *NotificationOutboxCreate { + _c.mutation.SetLastError(v) + return _c +} + +// SetNillableLastError sets the "last_error" field if the given value is not nil. +func (_c *NotificationOutboxCreate) SetNillableLastError(v *string) *NotificationOutboxCreate { + if v != nil { + _c.SetLastError(*v) + } + return _c +} + +// SetCreatedAt sets the "created_at" field. +func (_c *NotificationOutboxCreate) SetCreatedAt(v time.Time) *NotificationOutboxCreate { + _c.mutation.SetCreatedAt(v) + return _c +} + +// SetUpdatedAt sets the "updated_at" field. +func (_c *NotificationOutboxCreate) SetUpdatedAt(v time.Time) *NotificationOutboxCreate { + _c.mutation.SetUpdatedAt(v) + return _c +} + +// SetID sets the "id" field. +func (_c *NotificationOutboxCreate) SetID(v int) *NotificationOutboxCreate { + _c.mutation.SetID(v) + return _c +} + +// SetIncident sets the "incident" edge to the Incident entity. +func (_c *NotificationOutboxCreate) SetIncident(v *Incident) *NotificationOutboxCreate { + return _c.SetIncidentID(v.ID) +} + +// Mutation returns the NotificationOutboxMutation object of the builder. +func (_c *NotificationOutboxCreate) Mutation() *NotificationOutboxMutation { + return _c.mutation +} + +// Save creates the NotificationOutbox in the database. +func (_c *NotificationOutboxCreate) Save(ctx context.Context) (*NotificationOutbox, error) { + _c.defaults() + return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (_c *NotificationOutboxCreate) SaveX(ctx context.Context) *NotificationOutbox { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *NotificationOutboxCreate) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *NotificationOutboxCreate) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (_c *NotificationOutboxCreate) defaults() { + if _, ok := _c.mutation.Status(); !ok { + v := notificationoutbox.DefaultStatus + _c.mutation.SetStatus(v) + } + if _, ok := _c.mutation.Attempts(); !ok { + v := notificationoutbox.DefaultAttempts + _c.mutation.SetAttempts(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_c *NotificationOutboxCreate) check() error { + if _, ok := _c.mutation.Kind(); !ok { + return &ValidationError{Name: "kind", err: errors.New(`ent: missing required field "NotificationOutbox.kind"`)} + } + if v, ok := _c.mutation.Kind(); ok { + if err := notificationoutbox.KindValidator(v); err != nil { + return &ValidationError{Name: "kind", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.kind": %w`, err)} + } + } + if _, ok := _c.mutation.IncidentID(); !ok { + return &ValidationError{Name: "incident_id", err: errors.New(`ent: missing required field "NotificationOutbox.incident_id"`)} + } + if _, ok := _c.mutation.Recipient(); !ok { + return &ValidationError{Name: "recipient", err: errors.New(`ent: missing required field "NotificationOutbox.recipient"`)} + } + if v, ok := _c.mutation.Recipient(); ok { + if err := notificationoutbox.RecipientValidator(v); err != nil { + return &ValidationError{Name: "recipient", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.recipient": %w`, err)} + } + } + if _, ok := _c.mutation.Payload(); !ok { + return &ValidationError{Name: "payload", err: errors.New(`ent: missing required field "NotificationOutbox.payload"`)} + } + if _, ok := _c.mutation.ChangeID(); !ok { + return &ValidationError{Name: "change_id", err: errors.New(`ent: missing required field "NotificationOutbox.change_id"`)} + } + if v, ok := _c.mutation.ChangeID(); ok { + if err := notificationoutbox.ChangeIDValidator(v); err != nil { + return &ValidationError{Name: "change_id", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.change_id": %w`, err)} + } + } + if _, ok := _c.mutation.DedupKey(); !ok { + return &ValidationError{Name: "dedup_key", err: errors.New(`ent: missing required field "NotificationOutbox.dedup_key"`)} + } + if v, ok := _c.mutation.DedupKey(); ok { + if err := notificationoutbox.DedupKeyValidator(v); err != nil { + return &ValidationError{Name: "dedup_key", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.dedup_key": %w`, err)} + } + } + if _, ok := _c.mutation.Status(); !ok { + return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "NotificationOutbox.status"`)} + } + if _, ok := _c.mutation.Attempts(); !ok { + return &ValidationError{Name: "attempts", err: errors.New(`ent: missing required field "NotificationOutbox.attempts"`)} + } + if len(_c.mutation.IncidentIDs()) == 0 { + return &ValidationError{Name: "incident", err: errors.New(`ent: missing required edge "NotificationOutbox.incident"`)} + } + return nil +} + +func (_c *NotificationOutboxCreate) sqlSave(ctx context.Context) (*NotificationOutbox, error) { + if err := _c.check(); err != nil { + return nil, err + } + _node, _spec := _c.createSpec() + if err := sqlgraph.CreateNode(ctx, _c.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int(id) + } + _c.mutation.id = &_node.ID + _c.mutation.done = true + return _node, nil +} + +func (_c *NotificationOutboxCreate) createSpec() (*NotificationOutbox, *sqlgraph.CreateSpec) { + var ( + _node = &NotificationOutbox{config: _c.config} + _spec = sqlgraph.NewCreateSpec(notificationoutbox.Table, sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt)) + ) + _spec.OnConflict = _c.conflict + if id, ok := _c.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := _c.mutation.Kind(); ok { + _spec.SetField(notificationoutbox.FieldKind, field.TypeString, value) + _node.Kind = value + } + if value, ok := _c.mutation.Recipient(); ok { + _spec.SetField(notificationoutbox.FieldRecipient, field.TypeString, value) + _node.Recipient = value + } + if value, ok := _c.mutation.Payload(); ok { + _spec.SetField(notificationoutbox.FieldPayload, field.TypeJSON, value) + _node.Payload = value + } + if value, ok := _c.mutation.ChangeID(); ok { + _spec.SetField(notificationoutbox.FieldChangeID, field.TypeString, value) + _node.ChangeID = value + } + if value, ok := _c.mutation.DedupKey(); ok { + _spec.SetField(notificationoutbox.FieldDedupKey, field.TypeString, value) + _node.DedupKey = value + } + if value, ok := _c.mutation.Status(); ok { + _spec.SetField(notificationoutbox.FieldStatus, field.TypeString, value) + _node.Status = value + } + if value, ok := _c.mutation.Attempts(); ok { + _spec.SetField(notificationoutbox.FieldAttempts, field.TypeInt, value) + _node.Attempts = value + } + if value, ok := _c.mutation.NextAttemptAt(); ok { + _spec.SetField(notificationoutbox.FieldNextAttemptAt, field.TypeTime, value) + _node.NextAttemptAt = value + } + if value, ok := _c.mutation.LockedBy(); ok { + _spec.SetField(notificationoutbox.FieldLockedBy, field.TypeString, value) + _node.LockedBy = value + } + if value, ok := _c.mutation.LockedAt(); ok { + _spec.SetField(notificationoutbox.FieldLockedAt, field.TypeTime, value) + _node.LockedAt = value + } + if value, ok := _c.mutation.LastError(); ok { + _spec.SetField(notificationoutbox.FieldLastError, field.TypeString, value) + _node.LastError = value + } + if value, ok := _c.mutation.CreatedAt(); ok { + _spec.SetField(notificationoutbox.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := _c.mutation.UpdatedAt(); ok { + _spec.SetField(notificationoutbox.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if nodes := _c.mutation.IncidentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: notificationoutbox.IncidentTable, + Columns: []string{notificationoutbox.IncidentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.IncidentID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.NotificationOutbox.Create(). +// SetKind(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.NotificationOutboxUpsert) { +// SetKind(v+v). +// }). +// Exec(ctx) +func (_c *NotificationOutboxCreate) OnConflict(opts ...sql.ConflictOption) *NotificationOutboxUpsertOne { + _c.conflict = opts + return &NotificationOutboxUpsertOne{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.NotificationOutbox.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *NotificationOutboxCreate) OnConflictColumns(columns ...string) *NotificationOutboxUpsertOne { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &NotificationOutboxUpsertOne{ + create: _c, + } +} + +type ( + // NotificationOutboxUpsertOne is the builder for "upsert"-ing + // one NotificationOutbox node. + NotificationOutboxUpsertOne struct { + create *NotificationOutboxCreate + } + + // NotificationOutboxUpsert is the "OnConflict" setter. + NotificationOutboxUpsert struct { + *sql.UpdateSet + } +) + +// SetKind sets the "kind" field. +func (u *NotificationOutboxUpsert) SetKind(v string) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldKind, v) + return u +} + +// UpdateKind sets the "kind" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateKind() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldKind) + return u +} + +// SetIncidentID sets the "incident_id" field. +func (u *NotificationOutboxUpsert) SetIncidentID(v int) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldIncidentID, v) + return u +} + +// UpdateIncidentID sets the "incident_id" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateIncidentID() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldIncidentID) + return u +} + +// SetRecipient sets the "recipient" field. +func (u *NotificationOutboxUpsert) SetRecipient(v string) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldRecipient, v) + return u +} + +// UpdateRecipient sets the "recipient" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateRecipient() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldRecipient) + return u +} + +// SetPayload sets the "payload" field. +func (u *NotificationOutboxUpsert) SetPayload(v map[string]interface{}) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldPayload, v) + return u +} + +// UpdatePayload sets the "payload" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdatePayload() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldPayload) + return u +} + +// SetChangeID sets the "change_id" field. +func (u *NotificationOutboxUpsert) SetChangeID(v string) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldChangeID, v) + return u +} + +// UpdateChangeID sets the "change_id" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateChangeID() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldChangeID) + return u +} + +// SetDedupKey sets the "dedup_key" field. +func (u *NotificationOutboxUpsert) SetDedupKey(v string) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldDedupKey, v) + return u +} + +// UpdateDedupKey sets the "dedup_key" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateDedupKey() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldDedupKey) + return u +} + +// SetStatus sets the "status" field. +func (u *NotificationOutboxUpsert) SetStatus(v string) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldStatus, v) + return u +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateStatus() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldStatus) + return u +} + +// SetAttempts sets the "attempts" field. +func (u *NotificationOutboxUpsert) SetAttempts(v int) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldAttempts, v) + return u +} + +// UpdateAttempts sets the "attempts" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateAttempts() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldAttempts) + return u +} + +// AddAttempts adds v to the "attempts" field. +func (u *NotificationOutboxUpsert) AddAttempts(v int) *NotificationOutboxUpsert { + u.Add(notificationoutbox.FieldAttempts, v) + return u +} + +// SetNextAttemptAt sets the "next_attempt_at" field. +func (u *NotificationOutboxUpsert) SetNextAttemptAt(v time.Time) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldNextAttemptAt, v) + return u +} + +// UpdateNextAttemptAt sets the "next_attempt_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateNextAttemptAt() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldNextAttemptAt) + return u +} + +// ClearNextAttemptAt clears the value of the "next_attempt_at" field. +func (u *NotificationOutboxUpsert) ClearNextAttemptAt() *NotificationOutboxUpsert { + u.SetNull(notificationoutbox.FieldNextAttemptAt) + return u +} + +// SetLockedBy sets the "locked_by" field. +func (u *NotificationOutboxUpsert) SetLockedBy(v string) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldLockedBy, v) + return u +} + +// UpdateLockedBy sets the "locked_by" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateLockedBy() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldLockedBy) + return u +} + +// ClearLockedBy clears the value of the "locked_by" field. +func (u *NotificationOutboxUpsert) ClearLockedBy() *NotificationOutboxUpsert { + u.SetNull(notificationoutbox.FieldLockedBy) + return u +} + +// SetLockedAt sets the "locked_at" field. +func (u *NotificationOutboxUpsert) SetLockedAt(v time.Time) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldLockedAt, v) + return u +} + +// UpdateLockedAt sets the "locked_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateLockedAt() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldLockedAt) + return u +} + +// ClearLockedAt clears the value of the "locked_at" field. +func (u *NotificationOutboxUpsert) ClearLockedAt() *NotificationOutboxUpsert { + u.SetNull(notificationoutbox.FieldLockedAt) + return u +} + +// SetLastError sets the "last_error" field. +func (u *NotificationOutboxUpsert) SetLastError(v string) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldLastError, v) + return u +} + +// UpdateLastError sets the "last_error" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateLastError() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldLastError) + return u +} + +// ClearLastError clears the value of the "last_error" field. +func (u *NotificationOutboxUpsert) ClearLastError() *NotificationOutboxUpsert { + u.SetNull(notificationoutbox.FieldLastError) + return u +} + +// SetCreatedAt sets the "created_at" field. +func (u *NotificationOutboxUpsert) SetCreatedAt(v time.Time) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldCreatedAt, v) + return u +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateCreatedAt() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldCreatedAt) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *NotificationOutboxUpsert) SetUpdatedAt(v time.Time) *NotificationOutboxUpsert { + u.Set(notificationoutbox.FieldUpdatedAt, v) + return u +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsert) UpdateUpdatedAt() *NotificationOutboxUpsert { + u.SetExcluded(notificationoutbox.FieldUpdatedAt) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. +// Using this option is equivalent to using: +// +// client.NotificationOutbox.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(notificationoutbox.FieldID) +// }), +// ). +// Exec(ctx) +func (u *NotificationOutboxUpsertOne) UpdateNewValues() *NotificationOutboxUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.ID(); exists { + s.SetIgnore(notificationoutbox.FieldID) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.NotificationOutbox.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *NotificationOutboxUpsertOne) Ignore() *NotificationOutboxUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *NotificationOutboxUpsertOne) DoNothing() *NotificationOutboxUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the NotificationOutboxCreate.OnConflict +// documentation for more info. +func (u *NotificationOutboxUpsertOne) Update(set func(*NotificationOutboxUpsert)) *NotificationOutboxUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&NotificationOutboxUpsert{UpdateSet: update}) + })) + return u +} + +// SetKind sets the "kind" field. +func (u *NotificationOutboxUpsertOne) SetKind(v string) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetKind(v) + }) +} + +// UpdateKind sets the "kind" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateKind() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateKind() + }) +} + +// SetIncidentID sets the "incident_id" field. +func (u *NotificationOutboxUpsertOne) SetIncidentID(v int) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetIncidentID(v) + }) +} + +// UpdateIncidentID sets the "incident_id" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateIncidentID() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateIncidentID() + }) +} + +// SetRecipient sets the "recipient" field. +func (u *NotificationOutboxUpsertOne) SetRecipient(v string) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetRecipient(v) + }) +} + +// UpdateRecipient sets the "recipient" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateRecipient() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateRecipient() + }) +} + +// SetPayload sets the "payload" field. +func (u *NotificationOutboxUpsertOne) SetPayload(v map[string]interface{}) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetPayload(v) + }) +} + +// UpdatePayload sets the "payload" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdatePayload() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdatePayload() + }) +} + +// SetChangeID sets the "change_id" field. +func (u *NotificationOutboxUpsertOne) SetChangeID(v string) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetChangeID(v) + }) +} + +// UpdateChangeID sets the "change_id" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateChangeID() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateChangeID() + }) +} + +// SetDedupKey sets the "dedup_key" field. +func (u *NotificationOutboxUpsertOne) SetDedupKey(v string) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetDedupKey(v) + }) +} + +// UpdateDedupKey sets the "dedup_key" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateDedupKey() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateDedupKey() + }) +} + +// SetStatus sets the "status" field. +func (u *NotificationOutboxUpsertOne) SetStatus(v string) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateStatus() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateStatus() + }) +} + +// SetAttempts sets the "attempts" field. +func (u *NotificationOutboxUpsertOne) SetAttempts(v int) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetAttempts(v) + }) +} + +// AddAttempts adds v to the "attempts" field. +func (u *NotificationOutboxUpsertOne) AddAttempts(v int) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.AddAttempts(v) + }) +} + +// UpdateAttempts sets the "attempts" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateAttempts() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateAttempts() + }) +} + +// SetNextAttemptAt sets the "next_attempt_at" field. +func (u *NotificationOutboxUpsertOne) SetNextAttemptAt(v time.Time) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetNextAttemptAt(v) + }) +} + +// UpdateNextAttemptAt sets the "next_attempt_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateNextAttemptAt() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateNextAttemptAt() + }) +} + +// ClearNextAttemptAt clears the value of the "next_attempt_at" field. +func (u *NotificationOutboxUpsertOne) ClearNextAttemptAt() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.ClearNextAttemptAt() + }) +} + +// SetLockedBy sets the "locked_by" field. +func (u *NotificationOutboxUpsertOne) SetLockedBy(v string) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetLockedBy(v) + }) +} + +// UpdateLockedBy sets the "locked_by" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateLockedBy() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateLockedBy() + }) +} + +// ClearLockedBy clears the value of the "locked_by" field. +func (u *NotificationOutboxUpsertOne) ClearLockedBy() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.ClearLockedBy() + }) +} + +// SetLockedAt sets the "locked_at" field. +func (u *NotificationOutboxUpsertOne) SetLockedAt(v time.Time) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetLockedAt(v) + }) +} + +// UpdateLockedAt sets the "locked_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateLockedAt() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateLockedAt() + }) +} + +// ClearLockedAt clears the value of the "locked_at" field. +func (u *NotificationOutboxUpsertOne) ClearLockedAt() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.ClearLockedAt() + }) +} + +// SetLastError sets the "last_error" field. +func (u *NotificationOutboxUpsertOne) SetLastError(v string) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetLastError(v) + }) +} + +// UpdateLastError sets the "last_error" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateLastError() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateLastError() + }) +} + +// ClearLastError clears the value of the "last_error" field. +func (u *NotificationOutboxUpsertOne) ClearLastError() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.ClearLastError() + }) +} + +// SetCreatedAt sets the "created_at" field. +func (u *NotificationOutboxUpsertOne) SetCreatedAt(v time.Time) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateCreatedAt() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateCreatedAt() + }) +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *NotificationOutboxUpsertOne) SetUpdatedAt(v time.Time) *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsertOne) UpdateUpdatedAt() *NotificationOutboxUpsertOne { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateUpdatedAt() + }) +} + +// Exec executes the query. +func (u *NotificationOutboxUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for NotificationOutboxCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *NotificationOutboxUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *NotificationOutboxUpsertOne) ID(ctx context.Context) (id int, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *NotificationOutboxUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// NotificationOutboxCreateBulk is the builder for creating many NotificationOutbox entities in bulk. +type NotificationOutboxCreateBulk struct { + config + err error + builders []*NotificationOutboxCreate + conflict []sql.ConflictOption +} + +// Save creates the NotificationOutbox entities in the database. +func (_c *NotificationOutboxCreateBulk) Save(ctx context.Context) ([]*NotificationOutbox, error) { + if _c.err != nil { + return nil, _c.err + } + specs := make([]*sqlgraph.CreateSpec, len(_c.builders)) + nodes := make([]*NotificationOutbox, len(_c.builders)) + mutators := make([]Mutator, len(_c.builders)) + for i := range _c.builders { + func(i int, root context.Context) { + builder := _c.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*NotificationOutboxMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, _c.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = _c.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, _c.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, _c.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (_c *NotificationOutboxCreateBulk) SaveX(ctx context.Context) []*NotificationOutbox { + v, err := _c.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (_c *NotificationOutboxCreateBulk) Exec(ctx context.Context) error { + _, err := _c.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_c *NotificationOutboxCreateBulk) ExecX(ctx context.Context) { + if err := _c.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.NotificationOutbox.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.NotificationOutboxUpsert) { +// SetKind(v+v). +// }). +// Exec(ctx) +func (_c *NotificationOutboxCreateBulk) OnConflict(opts ...sql.ConflictOption) *NotificationOutboxUpsertBulk { + _c.conflict = opts + return &NotificationOutboxUpsertBulk{ + create: _c, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.NotificationOutbox.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (_c *NotificationOutboxCreateBulk) OnConflictColumns(columns ...string) *NotificationOutboxUpsertBulk { + _c.conflict = append(_c.conflict, sql.ConflictColumns(columns...)) + return &NotificationOutboxUpsertBulk{ + create: _c, + } +} + +// NotificationOutboxUpsertBulk is the builder for "upsert"-ing +// a bulk of NotificationOutbox nodes. +type NotificationOutboxUpsertBulk struct { + create *NotificationOutboxCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.NotificationOutbox.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(notificationoutbox.FieldID) +// }), +// ). +// Exec(ctx) +func (u *NotificationOutboxUpsertBulk) UpdateNewValues() *NotificationOutboxUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.ID(); exists { + s.SetIgnore(notificationoutbox.FieldID) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.NotificationOutbox.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *NotificationOutboxUpsertBulk) Ignore() *NotificationOutboxUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *NotificationOutboxUpsertBulk) DoNothing() *NotificationOutboxUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the NotificationOutboxCreateBulk.OnConflict +// documentation for more info. +func (u *NotificationOutboxUpsertBulk) Update(set func(*NotificationOutboxUpsert)) *NotificationOutboxUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&NotificationOutboxUpsert{UpdateSet: update}) + })) + return u +} + +// SetKind sets the "kind" field. +func (u *NotificationOutboxUpsertBulk) SetKind(v string) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetKind(v) + }) +} + +// UpdateKind sets the "kind" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateKind() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateKind() + }) +} + +// SetIncidentID sets the "incident_id" field. +func (u *NotificationOutboxUpsertBulk) SetIncidentID(v int) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetIncidentID(v) + }) +} + +// UpdateIncidentID sets the "incident_id" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateIncidentID() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateIncidentID() + }) +} + +// SetRecipient sets the "recipient" field. +func (u *NotificationOutboxUpsertBulk) SetRecipient(v string) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetRecipient(v) + }) +} + +// UpdateRecipient sets the "recipient" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateRecipient() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateRecipient() + }) +} + +// SetPayload sets the "payload" field. +func (u *NotificationOutboxUpsertBulk) SetPayload(v map[string]interface{}) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetPayload(v) + }) +} + +// UpdatePayload sets the "payload" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdatePayload() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdatePayload() + }) +} + +// SetChangeID sets the "change_id" field. +func (u *NotificationOutboxUpsertBulk) SetChangeID(v string) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetChangeID(v) + }) +} + +// UpdateChangeID sets the "change_id" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateChangeID() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateChangeID() + }) +} + +// SetDedupKey sets the "dedup_key" field. +func (u *NotificationOutboxUpsertBulk) SetDedupKey(v string) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetDedupKey(v) + }) +} + +// UpdateDedupKey sets the "dedup_key" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateDedupKey() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateDedupKey() + }) +} + +// SetStatus sets the "status" field. +func (u *NotificationOutboxUpsertBulk) SetStatus(v string) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateStatus() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateStatus() + }) +} + +// SetAttempts sets the "attempts" field. +func (u *NotificationOutboxUpsertBulk) SetAttempts(v int) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetAttempts(v) + }) +} + +// AddAttempts adds v to the "attempts" field. +func (u *NotificationOutboxUpsertBulk) AddAttempts(v int) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.AddAttempts(v) + }) +} + +// UpdateAttempts sets the "attempts" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateAttempts() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateAttempts() + }) +} + +// SetNextAttemptAt sets the "next_attempt_at" field. +func (u *NotificationOutboxUpsertBulk) SetNextAttemptAt(v time.Time) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetNextAttemptAt(v) + }) +} + +// UpdateNextAttemptAt sets the "next_attempt_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateNextAttemptAt() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateNextAttemptAt() + }) +} + +// ClearNextAttemptAt clears the value of the "next_attempt_at" field. +func (u *NotificationOutboxUpsertBulk) ClearNextAttemptAt() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.ClearNextAttemptAt() + }) +} + +// SetLockedBy sets the "locked_by" field. +func (u *NotificationOutboxUpsertBulk) SetLockedBy(v string) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetLockedBy(v) + }) +} + +// UpdateLockedBy sets the "locked_by" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateLockedBy() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateLockedBy() + }) +} + +// ClearLockedBy clears the value of the "locked_by" field. +func (u *NotificationOutboxUpsertBulk) ClearLockedBy() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.ClearLockedBy() + }) +} + +// SetLockedAt sets the "locked_at" field. +func (u *NotificationOutboxUpsertBulk) SetLockedAt(v time.Time) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetLockedAt(v) + }) +} + +// UpdateLockedAt sets the "locked_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateLockedAt() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateLockedAt() + }) +} + +// ClearLockedAt clears the value of the "locked_at" field. +func (u *NotificationOutboxUpsertBulk) ClearLockedAt() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.ClearLockedAt() + }) +} + +// SetLastError sets the "last_error" field. +func (u *NotificationOutboxUpsertBulk) SetLastError(v string) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetLastError(v) + }) +} + +// UpdateLastError sets the "last_error" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateLastError() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateLastError() + }) +} + +// ClearLastError clears the value of the "last_error" field. +func (u *NotificationOutboxUpsertBulk) ClearLastError() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.ClearLastError() + }) +} + +// SetCreatedAt sets the "created_at" field. +func (u *NotificationOutboxUpsertBulk) SetCreatedAt(v time.Time) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetCreatedAt(v) + }) +} + +// UpdateCreatedAt sets the "created_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateCreatedAt() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateCreatedAt() + }) +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *NotificationOutboxUpsertBulk) SetUpdatedAt(v time.Time) *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *NotificationOutboxUpsertBulk) UpdateUpdatedAt() *NotificationOutboxUpsertBulk { + return u.Update(func(s *NotificationOutboxUpsert) { + s.UpdateUpdatedAt() + }) +} + +// Exec executes the query. +func (u *NotificationOutboxUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the NotificationOutboxCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for NotificationOutboxCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *NotificationOutboxUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/notificationoutbox_delete.go b/ent/notificationoutbox_delete.go new file mode 100644 index 0000000..e4a5ecd --- /dev/null +++ b/ent/notificationoutbox_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// NotificationOutboxDelete is the builder for deleting a NotificationOutbox entity. +type NotificationOutboxDelete struct { + config + hooks []Hook + mutation *NotificationOutboxMutation +} + +// Where appends a list predicates to the NotificationOutboxDelete builder. +func (_d *NotificationOutboxDelete) Where(ps ...predicate.NotificationOutbox) *NotificationOutboxDelete { + _d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (_d *NotificationOutboxDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, _d.sqlExec, _d.mutation, _d.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *NotificationOutboxDelete) ExecX(ctx context.Context) int { + n, err := _d.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (_d *NotificationOutboxDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(notificationoutbox.Table, sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt)) + if ps := _d.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, _d.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + _d.mutation.done = true + return affected, err +} + +// NotificationOutboxDeleteOne is the builder for deleting a single NotificationOutbox entity. +type NotificationOutboxDeleteOne struct { + _d *NotificationOutboxDelete +} + +// Where appends a list predicates to the NotificationOutboxDelete builder. +func (_d *NotificationOutboxDeleteOne) Where(ps ...predicate.NotificationOutbox) *NotificationOutboxDeleteOne { + _d._d.mutation.Where(ps...) + return _d +} + +// Exec executes the deletion query. +func (_d *NotificationOutboxDeleteOne) Exec(ctx context.Context) error { + n, err := _d._d.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{notificationoutbox.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (_d *NotificationOutboxDeleteOne) ExecX(ctx context.Context) { + if err := _d.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/notificationoutbox_query.go b/ent/notificationoutbox_query.go new file mode 100644 index 0000000..683d6ce --- /dev/null +++ b/ent/notificationoutbox_query.go @@ -0,0 +1,606 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// NotificationOutboxQuery is the builder for querying NotificationOutbox entities. +type NotificationOutboxQuery struct { + config + ctx *QueryContext + order []notificationoutbox.OrderOption + inters []Interceptor + predicates []predicate.NotificationOutbox + withIncident *IncidentQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the NotificationOutboxQuery builder. +func (_q *NotificationOutboxQuery) Where(ps ...predicate.NotificationOutbox) *NotificationOutboxQuery { + _q.predicates = append(_q.predicates, ps...) + return _q +} + +// Limit the number of records to be returned by this query. +func (_q *NotificationOutboxQuery) Limit(limit int) *NotificationOutboxQuery { + _q.ctx.Limit = &limit + return _q +} + +// Offset to start from. +func (_q *NotificationOutboxQuery) Offset(offset int) *NotificationOutboxQuery { + _q.ctx.Offset = &offset + return _q +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (_q *NotificationOutboxQuery) Unique(unique bool) *NotificationOutboxQuery { + _q.ctx.Unique = &unique + return _q +} + +// Order specifies how the records should be ordered. +func (_q *NotificationOutboxQuery) Order(o ...notificationoutbox.OrderOption) *NotificationOutboxQuery { + _q.order = append(_q.order, o...) + return _q +} + +// QueryIncident chains the current query on the "incident" edge. +func (_q *NotificationOutboxQuery) QueryIncident() *IncidentQuery { + query := (&IncidentClient{config: _q.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + selector := _q.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(notificationoutbox.Table, notificationoutbox.FieldID, selector), + sqlgraph.To(incident.Table, incident.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, notificationoutbox.IncidentTable, notificationoutbox.IncidentColumn), + ) + fromU = sqlgraph.SetNeighbors(_q.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first NotificationOutbox entity from the query. +// Returns a *NotFoundError when no NotificationOutbox was found. +func (_q *NotificationOutboxQuery) First(ctx context.Context) (*NotificationOutbox, error) { + nodes, err := _q.Limit(1).All(setContextOp(ctx, _q.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{notificationoutbox.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (_q *NotificationOutboxQuery) FirstX(ctx context.Context) *NotificationOutbox { + node, err := _q.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first NotificationOutbox ID from the query. +// Returns a *NotFoundError when no NotificationOutbox ID was found. +func (_q *NotificationOutboxQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(1).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{notificationoutbox.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (_q *NotificationOutboxQuery) FirstIDX(ctx context.Context) int { + id, err := _q.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single NotificationOutbox entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one NotificationOutbox entity is found. +// Returns a *NotFoundError when no NotificationOutbox entities are found. +func (_q *NotificationOutboxQuery) Only(ctx context.Context) (*NotificationOutbox, error) { + nodes, err := _q.Limit(2).All(setContextOp(ctx, _q.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{notificationoutbox.Label} + default: + return nil, &NotSingularError{notificationoutbox.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (_q *NotificationOutboxQuery) OnlyX(ctx context.Context) *NotificationOutbox { + node, err := _q.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only NotificationOutbox ID in the query. +// Returns a *NotSingularError when more than one NotificationOutbox ID is found. +// Returns a *NotFoundError when no entities are found. +func (_q *NotificationOutboxQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = _q.Limit(2).IDs(setContextOp(ctx, _q.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{notificationoutbox.Label} + default: + err = &NotSingularError{notificationoutbox.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (_q *NotificationOutboxQuery) OnlyIDX(ctx context.Context) int { + id, err := _q.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of NotificationOutboxes. +func (_q *NotificationOutboxQuery) All(ctx context.Context) ([]*NotificationOutbox, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryAll) + if err := _q.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*NotificationOutbox, *NotificationOutboxQuery]() + return withInterceptors[[]*NotificationOutbox](ctx, _q, qr, _q.inters) +} + +// AllX is like All, but panics if an error occurs. +func (_q *NotificationOutboxQuery) AllX(ctx context.Context) []*NotificationOutbox { + nodes, err := _q.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of NotificationOutbox IDs. +func (_q *NotificationOutboxQuery) IDs(ctx context.Context) (ids []int, err error) { + if _q.ctx.Unique == nil && _q.path != nil { + _q.Unique(true) + } + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryIDs) + if err = _q.Select(notificationoutbox.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (_q *NotificationOutboxQuery) IDsX(ctx context.Context) []int { + ids, err := _q.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (_q *NotificationOutboxQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryCount) + if err := _q.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, _q, querierCount[*NotificationOutboxQuery](), _q.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (_q *NotificationOutboxQuery) CountX(ctx context.Context) int { + count, err := _q.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (_q *NotificationOutboxQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, _q.ctx, ent.OpQueryExist) + switch _, err := _q.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (_q *NotificationOutboxQuery) ExistX(ctx context.Context) bool { + exist, err := _q.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the NotificationOutboxQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (_q *NotificationOutboxQuery) Clone() *NotificationOutboxQuery { + if _q == nil { + return nil + } + return &NotificationOutboxQuery{ + config: _q.config, + ctx: _q.ctx.Clone(), + order: append([]notificationoutbox.OrderOption{}, _q.order...), + inters: append([]Interceptor{}, _q.inters...), + predicates: append([]predicate.NotificationOutbox{}, _q.predicates...), + withIncident: _q.withIncident.Clone(), + // clone intermediate query. + sql: _q.sql.Clone(), + path: _q.path, + } +} + +// WithIncident tells the query-builder to eager-load the nodes that are connected to +// the "incident" edge. The optional arguments are used to configure the query builder of the edge. +func (_q *NotificationOutboxQuery) WithIncident(opts ...func(*IncidentQuery)) *NotificationOutboxQuery { + query := (&IncidentClient{config: _q.config}).Query() + for _, opt := range opts { + opt(query) + } + _q.withIncident = query + return _q +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Kind string `json:"kind,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.NotificationOutbox.Query(). +// GroupBy(notificationoutbox.FieldKind). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (_q *NotificationOutboxQuery) GroupBy(field string, fields ...string) *NotificationOutboxGroupBy { + _q.ctx.Fields = append([]string{field}, fields...) + grbuild := &NotificationOutboxGroupBy{build: _q} + grbuild.flds = &_q.ctx.Fields + grbuild.label = notificationoutbox.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Kind string `json:"kind,omitempty"` +// } +// +// client.NotificationOutbox.Query(). +// Select(notificationoutbox.FieldKind). +// Scan(ctx, &v) +func (_q *NotificationOutboxQuery) Select(fields ...string) *NotificationOutboxSelect { + _q.ctx.Fields = append(_q.ctx.Fields, fields...) + sbuild := &NotificationOutboxSelect{NotificationOutboxQuery: _q} + sbuild.label = notificationoutbox.Label + sbuild.flds, sbuild.scan = &_q.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a NotificationOutboxSelect configured with the given aggregations. +func (_q *NotificationOutboxQuery) Aggregate(fns ...AggregateFunc) *NotificationOutboxSelect { + return _q.Select().Aggregate(fns...) +} + +func (_q *NotificationOutboxQuery) prepareQuery(ctx context.Context) error { + for _, inter := range _q.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, _q); err != nil { + return err + } + } + } + for _, f := range _q.ctx.Fields { + if !notificationoutbox.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if _q.path != nil { + prev, err := _q.path(ctx) + if err != nil { + return err + } + _q.sql = prev + } + return nil +} + +func (_q *NotificationOutboxQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*NotificationOutbox, error) { + var ( + nodes = []*NotificationOutbox{} + _spec = _q.querySpec() + loadedTypes = [1]bool{ + _q.withIncident != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*NotificationOutbox).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &NotificationOutbox{config: _q.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, _q.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := _q.withIncident; query != nil { + if err := _q.loadIncident(ctx, query, nodes, nil, + func(n *NotificationOutbox, e *Incident) { n.Edges.Incident = e }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (_q *NotificationOutboxQuery) loadIncident(ctx context.Context, query *IncidentQuery, nodes []*NotificationOutbox, init func(*NotificationOutbox), assign func(*NotificationOutbox, *Incident)) error { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*NotificationOutbox) + for i := range nodes { + fk := nodes[i].IncidentID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(incident.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "incident_id" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + +func (_q *NotificationOutboxQuery) sqlCount(ctx context.Context) (int, error) { + _spec := _q.querySpec() + _spec.Node.Columns = _q.ctx.Fields + if len(_q.ctx.Fields) > 0 { + _spec.Unique = _q.ctx.Unique != nil && *_q.ctx.Unique + } + return sqlgraph.CountNodes(ctx, _q.driver, _spec) +} + +func (_q *NotificationOutboxQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(notificationoutbox.Table, notificationoutbox.Columns, sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt)) + _spec.From = _q.sql + if unique := _q.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if _q.path != nil { + _spec.Unique = true + } + if fields := _q.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, notificationoutbox.FieldID) + for i := range fields { + if fields[i] != notificationoutbox.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + if _q.withIncident != nil { + _spec.Node.AddColumnOnce(notificationoutbox.FieldIncidentID) + } + } + if ps := _q.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := _q.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := _q.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := _q.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (_q *NotificationOutboxQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(_q.driver.Dialect()) + t1 := builder.Table(notificationoutbox.Table) + columns := _q.ctx.Fields + if len(columns) == 0 { + columns = notificationoutbox.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if _q.sql != nil { + selector = _q.sql + selector.Select(selector.Columns(columns...)...) + } + if _q.ctx.Unique != nil && *_q.ctx.Unique { + selector.Distinct() + } + for _, p := range _q.predicates { + p(selector) + } + for _, p := range _q.order { + p(selector) + } + if offset := _q.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := _q.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// NotificationOutboxGroupBy is the group-by builder for NotificationOutbox entities. +type NotificationOutboxGroupBy struct { + selector + build *NotificationOutboxQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (_g *NotificationOutboxGroupBy) Aggregate(fns ...AggregateFunc) *NotificationOutboxGroupBy { + _g.fns = append(_g.fns, fns...) + return _g +} + +// Scan applies the selector query and scans the result into the given value. +func (_g *NotificationOutboxGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _g.build.ctx, ent.OpQueryGroupBy) + if err := _g.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*NotificationOutboxQuery, *NotificationOutboxGroupBy](ctx, _g.build, _g, _g.build.inters, v) +} + +func (_g *NotificationOutboxGroupBy) sqlScan(ctx context.Context, root *NotificationOutboxQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(_g.fns)) + for _, fn := range _g.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*_g.flds)+len(_g.fns)) + for _, f := range *_g.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*_g.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _g.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// NotificationOutboxSelect is the builder for selecting fields of NotificationOutbox entities. +type NotificationOutboxSelect struct { + *NotificationOutboxQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (_s *NotificationOutboxSelect) Aggregate(fns ...AggregateFunc) *NotificationOutboxSelect { + _s.fns = append(_s.fns, fns...) + return _s +} + +// Scan applies the selector query and scans the result into the given value. +func (_s *NotificationOutboxSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, _s.ctx, ent.OpQuerySelect) + if err := _s.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*NotificationOutboxQuery, *NotificationOutboxSelect](ctx, _s.NotificationOutboxQuery, _s, _s.inters, v) +} + +func (_s *NotificationOutboxSelect) sqlScan(ctx context.Context, root *NotificationOutboxQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(_s.fns)) + for _, fn := range _s.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*_s.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := _s.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/notificationoutbox_update.go b/ent/notificationoutbox_update.go new file mode 100644 index 0000000..2be8b02 --- /dev/null +++ b/ent/notificationoutbox_update.go @@ -0,0 +1,865 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" + "github.com/stackmon/otc-status-dashboard/ent/predicate" +) + +// NotificationOutboxUpdate is the builder for updating NotificationOutbox entities. +type NotificationOutboxUpdate struct { + config + hooks []Hook + mutation *NotificationOutboxMutation +} + +// Where appends a list predicates to the NotificationOutboxUpdate builder. +func (_u *NotificationOutboxUpdate) Where(ps ...predicate.NotificationOutbox) *NotificationOutboxUpdate { + _u.mutation.Where(ps...) + return _u +} + +// SetKind sets the "kind" field. +func (_u *NotificationOutboxUpdate) SetKind(v string) *NotificationOutboxUpdate { + _u.mutation.SetKind(v) + return _u +} + +// SetNillableKind sets the "kind" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableKind(v *string) *NotificationOutboxUpdate { + if v != nil { + _u.SetKind(*v) + } + return _u +} + +// SetIncidentID sets the "incident_id" field. +func (_u *NotificationOutboxUpdate) SetIncidentID(v int) *NotificationOutboxUpdate { + _u.mutation.SetIncidentID(v) + return _u +} + +// SetNillableIncidentID sets the "incident_id" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableIncidentID(v *int) *NotificationOutboxUpdate { + if v != nil { + _u.SetIncidentID(*v) + } + return _u +} + +// SetRecipient sets the "recipient" field. +func (_u *NotificationOutboxUpdate) SetRecipient(v string) *NotificationOutboxUpdate { + _u.mutation.SetRecipient(v) + return _u +} + +// SetNillableRecipient sets the "recipient" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableRecipient(v *string) *NotificationOutboxUpdate { + if v != nil { + _u.SetRecipient(*v) + } + return _u +} + +// SetPayload sets the "payload" field. +func (_u *NotificationOutboxUpdate) SetPayload(v map[string]interface{}) *NotificationOutboxUpdate { + _u.mutation.SetPayload(v) + return _u +} + +// SetChangeID sets the "change_id" field. +func (_u *NotificationOutboxUpdate) SetChangeID(v string) *NotificationOutboxUpdate { + _u.mutation.SetChangeID(v) + return _u +} + +// SetNillableChangeID sets the "change_id" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableChangeID(v *string) *NotificationOutboxUpdate { + if v != nil { + _u.SetChangeID(*v) + } + return _u +} + +// SetDedupKey sets the "dedup_key" field. +func (_u *NotificationOutboxUpdate) SetDedupKey(v string) *NotificationOutboxUpdate { + _u.mutation.SetDedupKey(v) + return _u +} + +// SetNillableDedupKey sets the "dedup_key" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableDedupKey(v *string) *NotificationOutboxUpdate { + if v != nil { + _u.SetDedupKey(*v) + } + return _u +} + +// SetStatus sets the "status" field. +func (_u *NotificationOutboxUpdate) SetStatus(v string) *NotificationOutboxUpdate { + _u.mutation.SetStatus(v) + return _u +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableStatus(v *string) *NotificationOutboxUpdate { + if v != nil { + _u.SetStatus(*v) + } + return _u +} + +// SetAttempts sets the "attempts" field. +func (_u *NotificationOutboxUpdate) SetAttempts(v int) *NotificationOutboxUpdate { + _u.mutation.ResetAttempts() + _u.mutation.SetAttempts(v) + return _u +} + +// SetNillableAttempts sets the "attempts" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableAttempts(v *int) *NotificationOutboxUpdate { + if v != nil { + _u.SetAttempts(*v) + } + return _u +} + +// AddAttempts adds value to the "attempts" field. +func (_u *NotificationOutboxUpdate) AddAttempts(v int) *NotificationOutboxUpdate { + _u.mutation.AddAttempts(v) + return _u +} + +// SetNextAttemptAt sets the "next_attempt_at" field. +func (_u *NotificationOutboxUpdate) SetNextAttemptAt(v time.Time) *NotificationOutboxUpdate { + _u.mutation.SetNextAttemptAt(v) + return _u +} + +// SetNillableNextAttemptAt sets the "next_attempt_at" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableNextAttemptAt(v *time.Time) *NotificationOutboxUpdate { + if v != nil { + _u.SetNextAttemptAt(*v) + } + return _u +} + +// ClearNextAttemptAt clears the value of the "next_attempt_at" field. +func (_u *NotificationOutboxUpdate) ClearNextAttemptAt() *NotificationOutboxUpdate { + _u.mutation.ClearNextAttemptAt() + return _u +} + +// SetLockedBy sets the "locked_by" field. +func (_u *NotificationOutboxUpdate) SetLockedBy(v string) *NotificationOutboxUpdate { + _u.mutation.SetLockedBy(v) + return _u +} + +// SetNillableLockedBy sets the "locked_by" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableLockedBy(v *string) *NotificationOutboxUpdate { + if v != nil { + _u.SetLockedBy(*v) + } + return _u +} + +// ClearLockedBy clears the value of the "locked_by" field. +func (_u *NotificationOutboxUpdate) ClearLockedBy() *NotificationOutboxUpdate { + _u.mutation.ClearLockedBy() + return _u +} + +// SetLockedAt sets the "locked_at" field. +func (_u *NotificationOutboxUpdate) SetLockedAt(v time.Time) *NotificationOutboxUpdate { + _u.mutation.SetLockedAt(v) + return _u +} + +// SetNillableLockedAt sets the "locked_at" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableLockedAt(v *time.Time) *NotificationOutboxUpdate { + if v != nil { + _u.SetLockedAt(*v) + } + return _u +} + +// ClearLockedAt clears the value of the "locked_at" field. +func (_u *NotificationOutboxUpdate) ClearLockedAt() *NotificationOutboxUpdate { + _u.mutation.ClearLockedAt() + return _u +} + +// SetLastError sets the "last_error" field. +func (_u *NotificationOutboxUpdate) SetLastError(v string) *NotificationOutboxUpdate { + _u.mutation.SetLastError(v) + return _u +} + +// SetNillableLastError sets the "last_error" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableLastError(v *string) *NotificationOutboxUpdate { + if v != nil { + _u.SetLastError(*v) + } + return _u +} + +// ClearLastError clears the value of the "last_error" field. +func (_u *NotificationOutboxUpdate) ClearLastError() *NotificationOutboxUpdate { + _u.mutation.ClearLastError() + return _u +} + +// SetCreatedAt sets the "created_at" field. +func (_u *NotificationOutboxUpdate) SetCreatedAt(v time.Time) *NotificationOutboxUpdate { + _u.mutation.SetCreatedAt(v) + return _u +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableCreatedAt(v *time.Time) *NotificationOutboxUpdate { + if v != nil { + _u.SetCreatedAt(*v) + } + return _u +} + +// SetUpdatedAt sets the "updated_at" field. +func (_u *NotificationOutboxUpdate) SetUpdatedAt(v time.Time) *NotificationOutboxUpdate { + _u.mutation.SetUpdatedAt(v) + return _u +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (_u *NotificationOutboxUpdate) SetNillableUpdatedAt(v *time.Time) *NotificationOutboxUpdate { + if v != nil { + _u.SetUpdatedAt(*v) + } + return _u +} + +// SetIncident sets the "incident" edge to the Incident entity. +func (_u *NotificationOutboxUpdate) SetIncident(v *Incident) *NotificationOutboxUpdate { + return _u.SetIncidentID(v.ID) +} + +// Mutation returns the NotificationOutboxMutation object of the builder. +func (_u *NotificationOutboxUpdate) Mutation() *NotificationOutboxMutation { + return _u.mutation +} + +// ClearIncident clears the "incident" edge to the Incident entity. +func (_u *NotificationOutboxUpdate) ClearIncident() *NotificationOutboxUpdate { + _u.mutation.ClearIncident() + return _u +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (_u *NotificationOutboxUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *NotificationOutboxUpdate) SaveX(ctx context.Context) int { + affected, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (_u *NotificationOutboxUpdate) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *NotificationOutboxUpdate) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *NotificationOutboxUpdate) check() error { + if v, ok := _u.mutation.Kind(); ok { + if err := notificationoutbox.KindValidator(v); err != nil { + return &ValidationError{Name: "kind", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.kind": %w`, err)} + } + } + if v, ok := _u.mutation.Recipient(); ok { + if err := notificationoutbox.RecipientValidator(v); err != nil { + return &ValidationError{Name: "recipient", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.recipient": %w`, err)} + } + } + if v, ok := _u.mutation.ChangeID(); ok { + if err := notificationoutbox.ChangeIDValidator(v); err != nil { + return &ValidationError{Name: "change_id", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.change_id": %w`, err)} + } + } + if v, ok := _u.mutation.DedupKey(); ok { + if err := notificationoutbox.DedupKeyValidator(v); err != nil { + return &ValidationError{Name: "dedup_key", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.dedup_key": %w`, err)} + } + } + if _u.mutation.IncidentCleared() && len(_u.mutation.IncidentIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "NotificationOutbox.incident"`) + } + return nil +} + +func (_u *NotificationOutboxUpdate) sqlSave(ctx context.Context) (_node int, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(notificationoutbox.Table, notificationoutbox.Columns, sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt)) + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.Kind(); ok { + _spec.SetField(notificationoutbox.FieldKind, field.TypeString, value) + } + if value, ok := _u.mutation.Recipient(); ok { + _spec.SetField(notificationoutbox.FieldRecipient, field.TypeString, value) + } + if value, ok := _u.mutation.Payload(); ok { + _spec.SetField(notificationoutbox.FieldPayload, field.TypeJSON, value) + } + if value, ok := _u.mutation.ChangeID(); ok { + _spec.SetField(notificationoutbox.FieldChangeID, field.TypeString, value) + } + if value, ok := _u.mutation.DedupKey(); ok { + _spec.SetField(notificationoutbox.FieldDedupKey, field.TypeString, value) + } + if value, ok := _u.mutation.Status(); ok { + _spec.SetField(notificationoutbox.FieldStatus, field.TypeString, value) + } + if value, ok := _u.mutation.Attempts(); ok { + _spec.SetField(notificationoutbox.FieldAttempts, field.TypeInt, value) + } + if value, ok := _u.mutation.AddedAttempts(); ok { + _spec.AddField(notificationoutbox.FieldAttempts, field.TypeInt, value) + } + if value, ok := _u.mutation.NextAttemptAt(); ok { + _spec.SetField(notificationoutbox.FieldNextAttemptAt, field.TypeTime, value) + } + if _u.mutation.NextAttemptAtCleared() { + _spec.ClearField(notificationoutbox.FieldNextAttemptAt, field.TypeTime) + } + if value, ok := _u.mutation.LockedBy(); ok { + _spec.SetField(notificationoutbox.FieldLockedBy, field.TypeString, value) + } + if _u.mutation.LockedByCleared() { + _spec.ClearField(notificationoutbox.FieldLockedBy, field.TypeString) + } + if value, ok := _u.mutation.LockedAt(); ok { + _spec.SetField(notificationoutbox.FieldLockedAt, field.TypeTime, value) + } + if _u.mutation.LockedAtCleared() { + _spec.ClearField(notificationoutbox.FieldLockedAt, field.TypeTime) + } + if value, ok := _u.mutation.LastError(); ok { + _spec.SetField(notificationoutbox.FieldLastError, field.TypeString, value) + } + if _u.mutation.LastErrorCleared() { + _spec.ClearField(notificationoutbox.FieldLastError, field.TypeString) + } + if value, ok := _u.mutation.CreatedAt(); ok { + _spec.SetField(notificationoutbox.FieldCreatedAt, field.TypeTime, value) + } + if value, ok := _u.mutation.UpdatedAt(); ok { + _spec.SetField(notificationoutbox.FieldUpdatedAt, field.TypeTime, value) + } + if _u.mutation.IncidentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: notificationoutbox.IncidentTable, + Columns: []string{notificationoutbox.IncidentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.IncidentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: notificationoutbox.IncidentTable, + Columns: []string{notificationoutbox.IncidentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{notificationoutbox.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + _u.mutation.done = true + return _node, nil +} + +// NotificationOutboxUpdateOne is the builder for updating a single NotificationOutbox entity. +type NotificationOutboxUpdateOne struct { + config + fields []string + hooks []Hook + mutation *NotificationOutboxMutation +} + +// SetKind sets the "kind" field. +func (_u *NotificationOutboxUpdateOne) SetKind(v string) *NotificationOutboxUpdateOne { + _u.mutation.SetKind(v) + return _u +} + +// SetNillableKind sets the "kind" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableKind(v *string) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetKind(*v) + } + return _u +} + +// SetIncidentID sets the "incident_id" field. +func (_u *NotificationOutboxUpdateOne) SetIncidentID(v int) *NotificationOutboxUpdateOne { + _u.mutation.SetIncidentID(v) + return _u +} + +// SetNillableIncidentID sets the "incident_id" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableIncidentID(v *int) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetIncidentID(*v) + } + return _u +} + +// SetRecipient sets the "recipient" field. +func (_u *NotificationOutboxUpdateOne) SetRecipient(v string) *NotificationOutboxUpdateOne { + _u.mutation.SetRecipient(v) + return _u +} + +// SetNillableRecipient sets the "recipient" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableRecipient(v *string) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetRecipient(*v) + } + return _u +} + +// SetPayload sets the "payload" field. +func (_u *NotificationOutboxUpdateOne) SetPayload(v map[string]interface{}) *NotificationOutboxUpdateOne { + _u.mutation.SetPayload(v) + return _u +} + +// SetChangeID sets the "change_id" field. +func (_u *NotificationOutboxUpdateOne) SetChangeID(v string) *NotificationOutboxUpdateOne { + _u.mutation.SetChangeID(v) + return _u +} + +// SetNillableChangeID sets the "change_id" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableChangeID(v *string) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetChangeID(*v) + } + return _u +} + +// SetDedupKey sets the "dedup_key" field. +func (_u *NotificationOutboxUpdateOne) SetDedupKey(v string) *NotificationOutboxUpdateOne { + _u.mutation.SetDedupKey(v) + return _u +} + +// SetNillableDedupKey sets the "dedup_key" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableDedupKey(v *string) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetDedupKey(*v) + } + return _u +} + +// SetStatus sets the "status" field. +func (_u *NotificationOutboxUpdateOne) SetStatus(v string) *NotificationOutboxUpdateOne { + _u.mutation.SetStatus(v) + return _u +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableStatus(v *string) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetStatus(*v) + } + return _u +} + +// SetAttempts sets the "attempts" field. +func (_u *NotificationOutboxUpdateOne) SetAttempts(v int) *NotificationOutboxUpdateOne { + _u.mutation.ResetAttempts() + _u.mutation.SetAttempts(v) + return _u +} + +// SetNillableAttempts sets the "attempts" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableAttempts(v *int) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetAttempts(*v) + } + return _u +} + +// AddAttempts adds value to the "attempts" field. +func (_u *NotificationOutboxUpdateOne) AddAttempts(v int) *NotificationOutboxUpdateOne { + _u.mutation.AddAttempts(v) + return _u +} + +// SetNextAttemptAt sets the "next_attempt_at" field. +func (_u *NotificationOutboxUpdateOne) SetNextAttemptAt(v time.Time) *NotificationOutboxUpdateOne { + _u.mutation.SetNextAttemptAt(v) + return _u +} + +// SetNillableNextAttemptAt sets the "next_attempt_at" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableNextAttemptAt(v *time.Time) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetNextAttemptAt(*v) + } + return _u +} + +// ClearNextAttemptAt clears the value of the "next_attempt_at" field. +func (_u *NotificationOutboxUpdateOne) ClearNextAttemptAt() *NotificationOutboxUpdateOne { + _u.mutation.ClearNextAttemptAt() + return _u +} + +// SetLockedBy sets the "locked_by" field. +func (_u *NotificationOutboxUpdateOne) SetLockedBy(v string) *NotificationOutboxUpdateOne { + _u.mutation.SetLockedBy(v) + return _u +} + +// SetNillableLockedBy sets the "locked_by" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableLockedBy(v *string) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetLockedBy(*v) + } + return _u +} + +// ClearLockedBy clears the value of the "locked_by" field. +func (_u *NotificationOutboxUpdateOne) ClearLockedBy() *NotificationOutboxUpdateOne { + _u.mutation.ClearLockedBy() + return _u +} + +// SetLockedAt sets the "locked_at" field. +func (_u *NotificationOutboxUpdateOne) SetLockedAt(v time.Time) *NotificationOutboxUpdateOne { + _u.mutation.SetLockedAt(v) + return _u +} + +// SetNillableLockedAt sets the "locked_at" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableLockedAt(v *time.Time) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetLockedAt(*v) + } + return _u +} + +// ClearLockedAt clears the value of the "locked_at" field. +func (_u *NotificationOutboxUpdateOne) ClearLockedAt() *NotificationOutboxUpdateOne { + _u.mutation.ClearLockedAt() + return _u +} + +// SetLastError sets the "last_error" field. +func (_u *NotificationOutboxUpdateOne) SetLastError(v string) *NotificationOutboxUpdateOne { + _u.mutation.SetLastError(v) + return _u +} + +// SetNillableLastError sets the "last_error" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableLastError(v *string) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetLastError(*v) + } + return _u +} + +// ClearLastError clears the value of the "last_error" field. +func (_u *NotificationOutboxUpdateOne) ClearLastError() *NotificationOutboxUpdateOne { + _u.mutation.ClearLastError() + return _u +} + +// SetCreatedAt sets the "created_at" field. +func (_u *NotificationOutboxUpdateOne) SetCreatedAt(v time.Time) *NotificationOutboxUpdateOne { + _u.mutation.SetCreatedAt(v) + return _u +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableCreatedAt(v *time.Time) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetCreatedAt(*v) + } + return _u +} + +// SetUpdatedAt sets the "updated_at" field. +func (_u *NotificationOutboxUpdateOne) SetUpdatedAt(v time.Time) *NotificationOutboxUpdateOne { + _u.mutation.SetUpdatedAt(v) + return _u +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (_u *NotificationOutboxUpdateOne) SetNillableUpdatedAt(v *time.Time) *NotificationOutboxUpdateOne { + if v != nil { + _u.SetUpdatedAt(*v) + } + return _u +} + +// SetIncident sets the "incident" edge to the Incident entity. +func (_u *NotificationOutboxUpdateOne) SetIncident(v *Incident) *NotificationOutboxUpdateOne { + return _u.SetIncidentID(v.ID) +} + +// Mutation returns the NotificationOutboxMutation object of the builder. +func (_u *NotificationOutboxUpdateOne) Mutation() *NotificationOutboxMutation { + return _u.mutation +} + +// ClearIncident clears the "incident" edge to the Incident entity. +func (_u *NotificationOutboxUpdateOne) ClearIncident() *NotificationOutboxUpdateOne { + _u.mutation.ClearIncident() + return _u +} + +// Where appends a list predicates to the NotificationOutboxUpdate builder. +func (_u *NotificationOutboxUpdateOne) Where(ps ...predicate.NotificationOutbox) *NotificationOutboxUpdateOne { + _u.mutation.Where(ps...) + return _u +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (_u *NotificationOutboxUpdateOne) Select(field string, fields ...string) *NotificationOutboxUpdateOne { + _u.fields = append([]string{field}, fields...) + return _u +} + +// Save executes the query and returns the updated NotificationOutbox entity. +func (_u *NotificationOutboxUpdateOne) Save(ctx context.Context) (*NotificationOutbox, error) { + return withHooks(ctx, _u.sqlSave, _u.mutation, _u.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (_u *NotificationOutboxUpdateOne) SaveX(ctx context.Context) *NotificationOutbox { + node, err := _u.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (_u *NotificationOutboxUpdateOne) Exec(ctx context.Context) error { + _, err := _u.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (_u *NotificationOutboxUpdateOne) ExecX(ctx context.Context) { + if err := _u.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (_u *NotificationOutboxUpdateOne) check() error { + if v, ok := _u.mutation.Kind(); ok { + if err := notificationoutbox.KindValidator(v); err != nil { + return &ValidationError{Name: "kind", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.kind": %w`, err)} + } + } + if v, ok := _u.mutation.Recipient(); ok { + if err := notificationoutbox.RecipientValidator(v); err != nil { + return &ValidationError{Name: "recipient", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.recipient": %w`, err)} + } + } + if v, ok := _u.mutation.ChangeID(); ok { + if err := notificationoutbox.ChangeIDValidator(v); err != nil { + return &ValidationError{Name: "change_id", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.change_id": %w`, err)} + } + } + if v, ok := _u.mutation.DedupKey(); ok { + if err := notificationoutbox.DedupKeyValidator(v); err != nil { + return &ValidationError{Name: "dedup_key", err: fmt.Errorf(`ent: validator failed for field "NotificationOutbox.dedup_key": %w`, err)} + } + } + if _u.mutation.IncidentCleared() && len(_u.mutation.IncidentIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "NotificationOutbox.incident"`) + } + return nil +} + +func (_u *NotificationOutboxUpdateOne) sqlSave(ctx context.Context) (_node *NotificationOutbox, err error) { + if err := _u.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(notificationoutbox.Table, notificationoutbox.Columns, sqlgraph.NewFieldSpec(notificationoutbox.FieldID, field.TypeInt)) + id, ok := _u.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "NotificationOutbox.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := _u.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, notificationoutbox.FieldID) + for _, f := range fields { + if !notificationoutbox.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != notificationoutbox.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := _u.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := _u.mutation.Kind(); ok { + _spec.SetField(notificationoutbox.FieldKind, field.TypeString, value) + } + if value, ok := _u.mutation.Recipient(); ok { + _spec.SetField(notificationoutbox.FieldRecipient, field.TypeString, value) + } + if value, ok := _u.mutation.Payload(); ok { + _spec.SetField(notificationoutbox.FieldPayload, field.TypeJSON, value) + } + if value, ok := _u.mutation.ChangeID(); ok { + _spec.SetField(notificationoutbox.FieldChangeID, field.TypeString, value) + } + if value, ok := _u.mutation.DedupKey(); ok { + _spec.SetField(notificationoutbox.FieldDedupKey, field.TypeString, value) + } + if value, ok := _u.mutation.Status(); ok { + _spec.SetField(notificationoutbox.FieldStatus, field.TypeString, value) + } + if value, ok := _u.mutation.Attempts(); ok { + _spec.SetField(notificationoutbox.FieldAttempts, field.TypeInt, value) + } + if value, ok := _u.mutation.AddedAttempts(); ok { + _spec.AddField(notificationoutbox.FieldAttempts, field.TypeInt, value) + } + if value, ok := _u.mutation.NextAttemptAt(); ok { + _spec.SetField(notificationoutbox.FieldNextAttemptAt, field.TypeTime, value) + } + if _u.mutation.NextAttemptAtCleared() { + _spec.ClearField(notificationoutbox.FieldNextAttemptAt, field.TypeTime) + } + if value, ok := _u.mutation.LockedBy(); ok { + _spec.SetField(notificationoutbox.FieldLockedBy, field.TypeString, value) + } + if _u.mutation.LockedByCleared() { + _spec.ClearField(notificationoutbox.FieldLockedBy, field.TypeString) + } + if value, ok := _u.mutation.LockedAt(); ok { + _spec.SetField(notificationoutbox.FieldLockedAt, field.TypeTime, value) + } + if _u.mutation.LockedAtCleared() { + _spec.ClearField(notificationoutbox.FieldLockedAt, field.TypeTime) + } + if value, ok := _u.mutation.LastError(); ok { + _spec.SetField(notificationoutbox.FieldLastError, field.TypeString, value) + } + if _u.mutation.LastErrorCleared() { + _spec.ClearField(notificationoutbox.FieldLastError, field.TypeString) + } + if value, ok := _u.mutation.CreatedAt(); ok { + _spec.SetField(notificationoutbox.FieldCreatedAt, field.TypeTime, value) + } + if value, ok := _u.mutation.UpdatedAt(); ok { + _spec.SetField(notificationoutbox.FieldUpdatedAt, field.TypeTime, value) + } + if _u.mutation.IncidentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: notificationoutbox.IncidentTable, + Columns: []string{notificationoutbox.IncidentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := _u.mutation.IncidentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: notificationoutbox.IncidentTable, + Columns: []string{notificationoutbox.IncidentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(incident.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &NotificationOutbox{config: _u.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, _u.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{notificationoutbox.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + _u.mutation.done = true + return _node, nil +} diff --git a/ent/predicate/predicate.go b/ent/predicate/predicate.go new file mode 100644 index 0000000..d2f9775 --- /dev/null +++ b/ent/predicate/predicate.go @@ -0,0 +1,22 @@ +// Code generated by ent, DO NOT EDIT. + +package predicate + +import ( + "entgo.io/ent/dialect/sql" +) + +// Component is the predicate function for component builders. +type Component func(*sql.Selector) + +// ComponentAttr is the predicate function for componentattr builders. +type ComponentAttr func(*sql.Selector) + +// Incident is the predicate function for incident builders. +type Incident func(*sql.Selector) + +// IncidentStatus is the predicate function for incidentstatus builders. +type IncidentStatus func(*sql.Selector) + +// NotificationOutbox is the predicate function for notificationoutbox builders. +type NotificationOutbox func(*sql.Selector) diff --git a/ent/runtime.go b/ent/runtime.go new file mode 100644 index 0000000..6af3274 --- /dev/null +++ b/ent/runtime.go @@ -0,0 +1,84 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" + "github.com/stackmon/otc-status-dashboard/ent/schema" +) + +// The init function reads all schema descriptors with runtime code +// (default values, validators, hooks and policies) and stitches it +// to their package variables. +func init() { + componentFields := schema.Component{}.Fields() + _ = componentFields + // componentDescName is the schema descriptor for name field. + componentDescName := componentFields[1].Descriptor() + // component.NameValidator is a validator for the "name" field. It is called by the builders before save. + component.NameValidator = componentDescName.Validators[0].(func(string) error) + componentattrFields := schema.ComponentAttr{}.Fields() + _ = componentattrFields + // componentattrDescName is the schema descriptor for name field. + componentattrDescName := componentattrFields[2].Descriptor() + // componentattr.NameValidator is a validator for the "name" field. It is called by the builders before save. + componentattr.NameValidator = componentattrDescName.Validators[0].(func(string) error) + // componentattrDescValue is the schema descriptor for value field. + componentattrDescValue := componentattrFields[3].Descriptor() + // componentattr.ValueValidator is a validator for the "value" field. It is called by the builders before save. + componentattr.ValueValidator = componentattrDescValue.Validators[0].(func(string) error) + incidentFields := schema.Incident{}.Fields() + _ = incidentFields + // incidentDescText is the schema descriptor for text field. + incidentDescText := incidentFields[1].Descriptor() + // incident.TextValidator is a validator for the "text" field. It is called by the builders before save. + incident.TextValidator = incidentDescText.Validators[0].(func(string) error) + // incidentDescSystem is the schema descriptor for system field. + incidentDescSystem := incidentFields[6].Descriptor() + // incident.DefaultSystem holds the default value on creation for the system field. + incident.DefaultSystem = incidentDescSystem.Default.(bool) + // incidentDescVersion is the schema descriptor for version field. + incidentDescVersion := incidentFields[14].Descriptor() + // incident.DefaultVersion holds the default value on creation for the version field. + incident.DefaultVersion = incidentDescVersion.Default.(int) + incidentstatusFields := schema.IncidentStatus{}.Fields() + _ = incidentstatusFields + // incidentstatusDescText is the schema descriptor for text field. + incidentstatusDescText := incidentstatusFields[3].Descriptor() + // incidentstatus.TextValidator is a validator for the "text" field. It is called by the builders before save. + incidentstatus.TextValidator = incidentstatusDescText.Validators[0].(func(string) error) + // incidentstatusDescStatus is the schema descriptor for status field. + incidentstatusDescStatus := incidentstatusFields[4].Descriptor() + // incidentstatus.StatusValidator is a validator for the "status" field. It is called by the builders before save. + incidentstatus.StatusValidator = incidentstatusDescStatus.Validators[0].(func(string) error) + notificationoutboxFields := schema.NotificationOutbox{}.Fields() + _ = notificationoutboxFields + // notificationoutboxDescKind is the schema descriptor for kind field. + notificationoutboxDescKind := notificationoutboxFields[1].Descriptor() + // notificationoutbox.KindValidator is a validator for the "kind" field. It is called by the builders before save. + notificationoutbox.KindValidator = notificationoutboxDescKind.Validators[0].(func(string) error) + // notificationoutboxDescRecipient is the schema descriptor for recipient field. + notificationoutboxDescRecipient := notificationoutboxFields[3].Descriptor() + // notificationoutbox.RecipientValidator is a validator for the "recipient" field. It is called by the builders before save. + notificationoutbox.RecipientValidator = notificationoutboxDescRecipient.Validators[0].(func(string) error) + // notificationoutboxDescChangeID is the schema descriptor for change_id field. + notificationoutboxDescChangeID := notificationoutboxFields[5].Descriptor() + // notificationoutbox.ChangeIDValidator is a validator for the "change_id" field. It is called by the builders before save. + notificationoutbox.ChangeIDValidator = notificationoutboxDescChangeID.Validators[0].(func(string) error) + // notificationoutboxDescDedupKey is the schema descriptor for dedup_key field. + notificationoutboxDescDedupKey := notificationoutboxFields[6].Descriptor() + // notificationoutbox.DedupKeyValidator is a validator for the "dedup_key" field. It is called by the builders before save. + notificationoutbox.DedupKeyValidator = notificationoutboxDescDedupKey.Validators[0].(func(string) error) + // notificationoutboxDescStatus is the schema descriptor for status field. + notificationoutboxDescStatus := notificationoutboxFields[7].Descriptor() + // notificationoutbox.DefaultStatus holds the default value on creation for the status field. + notificationoutbox.DefaultStatus = notificationoutboxDescStatus.Default.(string) + // notificationoutboxDescAttempts is the schema descriptor for attempts field. + notificationoutboxDescAttempts := notificationoutboxFields[8].Descriptor() + // notificationoutbox.DefaultAttempts holds the default value on creation for the attempts field. + notificationoutbox.DefaultAttempts = notificationoutboxDescAttempts.Default.(int) +} diff --git a/ent/runtime/runtime.go b/ent/runtime/runtime.go new file mode 100644 index 0000000..8933eee --- /dev/null +++ b/ent/runtime/runtime.go @@ -0,0 +1,10 @@ +// Code generated by ent, DO NOT EDIT. + +package runtime + +// The schema-stitching logic is generated in github.com/stackmon/otc-status-dashboard/ent/runtime.go + +const ( + Version = "v0.14.6" // Version of ent codegen. + Sum = "h1:/f2696BpwuWAEEG6PVGWflg6+Inrpq4pRWuNlWz/Skk=" // Sum of ent codegen. +) diff --git a/ent/schema/component.go b/ent/schema/component.go new file mode 100644 index 0000000..1864987 --- /dev/null +++ b/ent/schema/component.go @@ -0,0 +1,52 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" +) + +// Component maps the `component` table. +type Component struct { + ent.Schema +} + +func (Component) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{Table: "component"}, + } +} + +func (Component) Fields() []ent.Field { + return []ent.Field{ + field.Int("id"). + SchemaType(map[string]string{"postgres": "serial"}), + field.String("name").NotEmpty(), + field.Time("created_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.Time("modified_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.Time("deleted_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + } +} + +func (Component) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("attributes", ComponentAttr.Type). + StorageKey(edge.Symbol("component_attribute_component_id_fkey")). + Annotations(entsql.OnDelete(entsql.NoAction)), + edge.From("incidents", Incident.Type). + Ref("components"), + } +} + +func (Component) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("id"). + StorageKey("ix_component_id"), + } +} diff --git a/ent/schema/componentattr.go b/ent/schema/componentattr.go new file mode 100644 index 0000000..5eb34a5 --- /dev/null +++ b/ent/schema/componentattr.go @@ -0,0 +1,53 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" +) + +// ComponentAttr maps the `component_attribute` table. +type ComponentAttr struct { + ent.Schema +} + +func (ComponentAttr) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{Table: "component_attribute"}, + } +} + +func (ComponentAttr) Fields() []ent.Field { + return []ent.Field{ + field.Int("id"). + SchemaType(map[string]string{"postgres": "serial"}), + field.Int("component_id").Optional(). + SchemaType(map[string]string{"postgres": "integer"}), + field.String("name").NotEmpty(), + field.String("value").NotEmpty(), + } +} + +func (ComponentAttr) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("component", Component.Type). + Ref("attributes"). + Field("component_id"). + Unique(), + } +} + +func (ComponentAttr) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("id"). + StorageKey("ix_component_attribute_id"), + index.Fields("component_id"). + StorageKey("ix_component_attribute_component_id"), + index.Fields("component_id", "name"). + Unique(). + StorageKey("unique_component_attribute"), + } +} diff --git a/ent/schema/incident.go b/ent/schema/incident.go new file mode 100644 index 0000000..58e6dde --- /dev/null +++ b/ent/schema/incident.go @@ -0,0 +1,78 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" +) + +// Incident maps the `incident` table. +type Incident struct { + ent.Schema +} + +func (Incident) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{Table: "incident"}, + } +} + +func (Incident) Fields() []ent.Field { + return []ent.Field{ + field.Int("id"). + SchemaType(map[string]string{"postgres": "serial"}), + field.String("text").NotEmpty(), + field.String("description").Optional(). + SchemaType(map[string]string{"postgres": "varchar(1500)"}), + field.Time("start_date"). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.Time("end_date").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.Int("impact"). + SchemaType(map[string]string{"postgres": "smallint"}), + field.Bool("system").Default(false), + field.Enum("type"). + Values("incident", "info", "maintenance"). + SchemaType(map[string]string{"postgres": "varchar"}), + field.String("status").Optional(). + SchemaType(map[string]string{"postgres": "varchar(50)"}), + field.Time("created_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.Time("modified_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.Time("deleted_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.String("created_by").Optional(). + SchemaType(map[string]string{"postgres": "varchar(255)"}), + field.String("contact_email").Optional(). + SchemaType(map[string]string{"postgres": "varchar(255)"}), + field.Int("version").Default(1). + SchemaType(map[string]string{"postgres": "integer"}), + } +} + +func (Incident) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("components", Component.Type). + StorageKey( + edge.Table("incident_component_relation"), + edge.Columns("incident_id", "component_id"), + edge.Symbols( + "incident_component_relation_incident_id_fkey", + "incident_component_relation_component_id_fkey", + ), + ), + edge.To("notifications", NotificationOutbox.Type). + StorageKey(edge.Symbol("notification_outbox_incident_id_fkey")), + } +} + +func (Incident) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("id"). + StorageKey("ix_incident_id"), + } +} diff --git a/ent/schema/incidentstatus.go b/ent/schema/incidentstatus.go new file mode 100644 index 0000000..59cf9a0 --- /dev/null +++ b/ent/schema/incidentstatus.go @@ -0,0 +1,57 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" +) + +// IncidentStatus maps the `incident_status` table. +// +// Note: production has NO foreign key on incident_status.incident_id, so +// incident_id is kept as a plain column (no edge) to match the production DDL. +type IncidentStatus struct { + ent.Schema +} + +func (IncidentStatus) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{Table: "incident_status"}, + } +} + +func (IncidentStatus) Fields() []ent.Field { + return []ent.Field{ + field.Int("id"). + SchemaType(map[string]string{"postgres": "serial"}), + field.Int("incident_id").Optional(). + SchemaType(map[string]string{"postgres": "integer"}), + field.Time("timestamp"). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.String("text").NotEmpty(), + field.String("status").NotEmpty(), + field.Time("created_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.Time("modified_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.Time("deleted_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamp"}), + field.String("created_by").Optional(). + SchemaType(map[string]string{"postgres": "varchar(255)"}), + field.String("modified_by").Optional(). + SchemaType(map[string]string{"postgres": "varchar(255)"}), + } +} + +func (IncidentStatus) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("id"). + StorageKey("ix_incident_status_id"), + index.Fields("incident_id"). + StorageKey("ix_incident_status_incident_id"), + index.Fields("incident_id", "timestamp"). + StorageKey("idx_incident_status_incident_id_timestamp"), + } +} diff --git a/ent/schema/notificationoutbox.go b/ent/schema/notificationoutbox.go new file mode 100644 index 0000000..c59c2aa --- /dev/null +++ b/ent/schema/notificationoutbox.go @@ -0,0 +1,88 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" +) + +// NotificationOutbox maps the `notification_outbox` table. +// +// Introduced by migration 000008 (not yet applied to production, which is at +// version 7). The DDL below matches that migration exactly, including the +// partial indexes. +type NotificationOutbox struct { + ent.Schema +} + +func (NotificationOutbox) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{Table: "notification_outbox"}, + } +} + +func (NotificationOutbox) Fields() []ent.Field { + return []ent.Field{ + field.Int("id"). + SchemaType(map[string]string{"postgres": "serial"}), + field.String("kind").NotEmpty(). + SchemaType(map[string]string{"postgres": "varchar(64)"}), + field.Int("incident_id"). + SchemaType(map[string]string{"postgres": "integer"}), + field.String("recipient").NotEmpty(). + SchemaType(map[string]string{"postgres": "varchar(255)"}), + field.JSON("payload", map[string]any{}). + SchemaType(map[string]string{"postgres": "jsonb"}), + field.String("change_id").NotEmpty(). + SchemaType(map[string]string{"postgres": "uuid"}), + field.String("dedup_key").NotEmpty(). + SchemaType(map[string]string{"postgres": "varchar(255)"}), + field.String("status").Default("pending"). + SchemaType(map[string]string{"postgres": "varchar(20)"}), + field.Int("attempts").Default(0). + SchemaType(map[string]string{"postgres": "integer"}), + field.Time("next_attempt_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamptz"}), + field.String("locked_by").Optional(). + SchemaType(map[string]string{"postgres": "varchar(255)"}), + field.Time("locked_at").Optional(). + SchemaType(map[string]string{"postgres": "timestamptz"}), + field.Text("last_error").Optional(), + field.Time("created_at"). + Annotations(entsql.DefaultExpr("NOW()")). + SchemaType(map[string]string{"postgres": "timestamptz"}), + field.Time("updated_at"). + Annotations(entsql.DefaultExpr("NOW()")). + SchemaType(map[string]string{"postgres": "timestamptz"}), + } +} + +func (NotificationOutbox) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("incident", Incident.Type). + Ref("notifications"). + Field("incident_id"). + Unique(). + Required(), + } +} + +func (NotificationOutbox) Indexes() []ent.Index { + return []ent.Index{ + index.Fields("dedup_key"). + Unique(). + StorageKey("idx_outbox_dedup"), + index.Fields("next_attempt_at"). + StorageKey("idx_outbox_dispatch"). + Annotations(entsql.IndexWhere("status = 'pending'")), + index.Fields("locked_at"). + StorageKey("idx_outbox_stale_processing"). + Annotations(entsql.IndexWhere("status = 'processing'")), + index.Fields("updated_at"). + StorageKey("idx_outbox_retention"). + Annotations(entsql.IndexWhere("status = 'sent'")), + } +} diff --git a/ent/tx.go b/ent/tx.go new file mode 100644 index 0000000..c0a96a7 --- /dev/null +++ b/ent/tx.go @@ -0,0 +1,222 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "sync" + + "entgo.io/ent/dialect" +) + +// Tx is a transactional client that is created by calling Client.Tx(). +type Tx struct { + config + // Component is the client for interacting with the Component builders. + Component *ComponentClient + // ComponentAttr is the client for interacting with the ComponentAttr builders. + ComponentAttr *ComponentAttrClient + // Incident is the client for interacting with the Incident builders. + Incident *IncidentClient + // IncidentStatus is the client for interacting with the IncidentStatus builders. + IncidentStatus *IncidentStatusClient + // NotificationOutbox is the client for interacting with the NotificationOutbox builders. + NotificationOutbox *NotificationOutboxClient + + // lazily loaded. + client *Client + clientOnce sync.Once + // ctx lives for the life of the transaction. It is + // the same context used by the underlying connection. + ctx context.Context +} + +type ( + // Committer is the interface that wraps the Commit method. + Committer interface { + Commit(context.Context, *Tx) error + } + + // The CommitFunc type is an adapter to allow the use of ordinary + // function as a Committer. If f is a function with the appropriate + // signature, CommitFunc(f) is a Committer that calls f. + CommitFunc func(context.Context, *Tx) error + + // CommitHook defines the "commit middleware". A function that gets a Committer + // and returns a Committer. For example: + // + // hook := func(next ent.Committer) ent.Committer { + // return ent.CommitFunc(func(ctx context.Context, tx *ent.Tx) error { + // // Do some stuff before. + // if err := next.Commit(ctx, tx); err != nil { + // return err + // } + // // Do some stuff after. + // return nil + // }) + // } + // + CommitHook func(Committer) Committer +) + +// Commit calls f(ctx, m). +func (f CommitFunc) Commit(ctx context.Context, tx *Tx) error { + return f(ctx, tx) +} + +// Commit commits the transaction. +func (tx *Tx) Commit() error { + txDriver := tx.config.driver.(*txDriver) + var fn Committer = CommitFunc(func(context.Context, *Tx) error { + return txDriver.tx.Commit() + }) + txDriver.mu.Lock() + hooks := append([]CommitHook(nil), txDriver.onCommit...) + txDriver.mu.Unlock() + for i := len(hooks) - 1; i >= 0; i-- { + fn = hooks[i](fn) + } + return fn.Commit(tx.ctx, tx) +} + +// OnCommit adds a hook to call on commit. +func (tx *Tx) OnCommit(f CommitHook) { + txDriver := tx.config.driver.(*txDriver) + txDriver.mu.Lock() + txDriver.onCommit = append(txDriver.onCommit, f) + txDriver.mu.Unlock() +} + +type ( + // Rollbacker is the interface that wraps the Rollback method. + Rollbacker interface { + Rollback(context.Context, *Tx) error + } + + // The RollbackFunc type is an adapter to allow the use of ordinary + // function as a Rollbacker. If f is a function with the appropriate + // signature, RollbackFunc(f) is a Rollbacker that calls f. + RollbackFunc func(context.Context, *Tx) error + + // RollbackHook defines the "rollback middleware". A function that gets a Rollbacker + // and returns a Rollbacker. For example: + // + // hook := func(next ent.Rollbacker) ent.Rollbacker { + // return ent.RollbackFunc(func(ctx context.Context, tx *ent.Tx) error { + // // Do some stuff before. + // if err := next.Rollback(ctx, tx); err != nil { + // return err + // } + // // Do some stuff after. + // return nil + // }) + // } + // + RollbackHook func(Rollbacker) Rollbacker +) + +// Rollback calls f(ctx, m). +func (f RollbackFunc) Rollback(ctx context.Context, tx *Tx) error { + return f(ctx, tx) +} + +// Rollback rollbacks the transaction. +func (tx *Tx) Rollback() error { + txDriver := tx.config.driver.(*txDriver) + var fn Rollbacker = RollbackFunc(func(context.Context, *Tx) error { + return txDriver.tx.Rollback() + }) + txDriver.mu.Lock() + hooks := append([]RollbackHook(nil), txDriver.onRollback...) + txDriver.mu.Unlock() + for i := len(hooks) - 1; i >= 0; i-- { + fn = hooks[i](fn) + } + return fn.Rollback(tx.ctx, tx) +} + +// OnRollback adds a hook to call on rollback. +func (tx *Tx) OnRollback(f RollbackHook) { + txDriver := tx.config.driver.(*txDriver) + txDriver.mu.Lock() + txDriver.onRollback = append(txDriver.onRollback, f) + txDriver.mu.Unlock() +} + +// Client returns a Client that binds to current transaction. +func (tx *Tx) Client() *Client { + tx.clientOnce.Do(func() { + tx.client = &Client{config: tx.config} + tx.client.init() + }) + return tx.client +} + +func (tx *Tx) init() { + tx.Component = NewComponentClient(tx.config) + tx.ComponentAttr = NewComponentAttrClient(tx.config) + tx.Incident = NewIncidentClient(tx.config) + tx.IncidentStatus = NewIncidentStatusClient(tx.config) + tx.NotificationOutbox = NewNotificationOutboxClient(tx.config) +} + +// txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation. +// The idea is to support transactions without adding any extra code to the builders. +// When a builder calls to driver.Tx(), it gets the same dialect.Tx instance. +// Commit and Rollback are nop for the internal builders and the user must call one +// of them in order to commit or rollback the transaction. +// +// If a closed transaction is embedded in one of the generated entities, and the entity +// applies a query, for example: Component.QueryXXX(), the query will be executed +// through the driver which created this transaction. +// +// Note that txDriver is not goroutine safe. +type txDriver struct { + // the driver we started the transaction from. + drv dialect.Driver + // tx is the underlying transaction. + tx dialect.Tx + // completion hooks. + mu sync.Mutex + onCommit []CommitHook + onRollback []RollbackHook +} + +// newTx creates a new transactional driver. +func newTx(ctx context.Context, drv dialect.Driver) (*txDriver, error) { + tx, err := drv.Tx(ctx) + if err != nil { + return nil, err + } + return &txDriver{tx: tx, drv: drv}, nil +} + +// Tx returns the transaction wrapper (txDriver) to avoid Commit or Rollback calls +// from the internal builders. Should be called only by the internal builders. +func (tx *txDriver) Tx(context.Context) (dialect.Tx, error) { return tx, nil } + +// Dialect returns the dialect of the driver we started the transaction from. +func (tx *txDriver) Dialect() string { return tx.drv.Dialect() } + +// Close is a nop close. +func (*txDriver) Close() error { return nil } + +// Commit is a nop commit for the internal builders. +// User must call `Tx.Commit` in order to commit the transaction. +func (*txDriver) Commit() error { return nil } + +// Rollback is a nop rollback for the internal builders. +// User must call `Tx.Rollback` in order to rollback the transaction. +func (*txDriver) Rollback() error { return nil } + +// Exec calls tx.Exec. +func (tx *txDriver) Exec(ctx context.Context, query string, args, v any) error { + return tx.tx.Exec(ctx, query, args, v) +} + +// Query calls tx.Query. +func (tx *txDriver) Query(ctx context.Context, query string, args, v any) error { + return tx.tx.Query(ctx, query, args, v) +} + +var _ dialect.Driver = (*txDriver)(nil) diff --git a/go.mod b/go.mod index bc5d35c..87c7eb5 100644 --- a/go.mod +++ b/go.mod @@ -27,15 +27,23 @@ require ( ) require ( + ariga.io/atlas v0.36.2-0.20250730182955-2c6300d0a3e1 // indirect dario.cat/mergo v1.0.2 // indirect + entgo.io/ent v0.14.6 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/agext/levenshtein v1.2.3 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bmatcuk/doublestar v1.3.4 // indirect github.com/bytedance/gopkg v0.1.4 // indirect github.com/bytedance/sonic v1.15.4 // indirect github.com/bytedance/sonic/loader v0.5.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/clipperhouse/displaywidth v0.6.2 // indirect + github.com/clipperhouse/stringish v0.1.1 // indirect + github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.7 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect @@ -46,6 +54,7 @@ require ( github.com/docker/go-connections v0.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/ebitengine/purego v0.10.1 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.1.0 // indirect github.com/gabriel-vasile/mimetype v1.4.15 // indirect github.com/gin-contrib/sse v1.1.2 // indirect @@ -53,11 +62,15 @@ require ( github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-openapi/inflect v0.19.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.2 // indirect github.com/go-playground/validator/v10 v10.30.5 // indirect github.com/goccy/go-json v0.10.6 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/hashicorp/hcl/v2 v2.18.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.11.0 // indirect @@ -71,7 +84,10 @@ require ( github.com/lib/pq v1.10.9 // indirect github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect github.com/magiconair/properties v1.8.10 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.24 // indirect + github.com/mattn/go-runewidth v0.0.19 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/go-archive v0.3.0 // indirect github.com/moby/moby/api v1.55.0 // indirect @@ -84,6 +100,10 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 // indirect + github.com/olekukonko/tablewriter v1.1.3 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pelletier/go-toml/v2 v2.4.3 // indirect @@ -95,11 +115,15 @@ require ( github.com/quic-go/quic-go v0.63.0 // indirect github.com/shirou/gopsutil/v4 v4.26.6 // indirect github.com/sirupsen/logrus v1.9.4 // indirect + github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect github.com/tklauser/go-sysconf v0.4.0 // indirect github.com/tklauser/numcpus v0.12.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.2 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect + github.com/zclconf/go-cty v1.14.4 // indirect + github.com/zclconf/go-cty-yaml v1.1.0 // indirect go.mongodb.org/mongo-driver/v2 v2.9.1 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 // indirect @@ -110,9 +134,11 @@ require ( go.yaml.in/yaml/v3 v3.0.5 // indirect golang.org/x/arch v0.31.0 // indirect golang.org/x/crypto v0.57.0 // indirect + golang.org/x/mod v0.41.0 // indirect golang.org/x/net v0.59.0 // indirect golang.org/x/oauth2 v0.37.0 // indirect golang.org/x/sys v0.48.0 // indirect golang.org/x/text v0.42.0 // indirect + golang.org/x/tools v0.49.0 // indirect google.golang.org/protobuf v1.36.12 // indirect ) diff --git a/go.sum b/go.sum index 96bdbcd..8228984 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ +ariga.io/atlas v0.36.2-0.20250730182955-2c6300d0a3e1 h1:NPPfBaVZgz4LKBCIc0FbMogCjvXN+yGf7CZwotOwJo8= +ariga.io/atlas v0.36.2-0.20250730182955-2c6300d0a3e1/go.mod h1:Ex5l1xHsnWQUc3wYnrJ9gD7RUEzG76P7ZRQp8wNr0wc= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +entgo.io/ent v0.14.6 h1:/f2696BpwuWAEEG6PVGWflg6+Inrpq4pRWuNlWz/Skk= +entgo.io/ent v0.14.6/go.mod h1:z46QBUdGC+BATwsedbDuREfSS0oSCV+csdEYlL4p73s= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= @@ -8,9 +12,15 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.15.4 h1:FgtV/4aBHpla9AxuMpuuzVUpa/Cf3izufkxNmnEzdI8= @@ -21,6 +31,12 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo= +github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= +github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= +github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= +github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= +github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI= github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -35,6 +51,7 @@ github.com/coreos/go-oidc/v3 v3.21.0 h1:wZo4Q9Pum8dYEj0eMUPrqR+kvuGkeUplbLpNCkBq github.com/coreos/go-oidc/v3 v3.21.0/go.mod h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4= github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -53,6 +70,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/ebitengine/purego v0.10.1 h1:dewVBCBT2GaMu1SrNTYxQhgQBethzfhiwvZiLGP/qyY= github.com/ebitengine/purego v0.10.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc= github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE= github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI= @@ -71,6 +90,8 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= +github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -94,6 +115,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= +github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo= +github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= @@ -135,12 +160,19 @@ github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRt github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= +github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= +github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI= github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.3.0 h1:nos4BtzzUIqB406BgQnWGMI4qib9BZ8XUHU+ucv/n1c= @@ -168,6 +200,14 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= +github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 h1:jrYnow5+hy3WRDCBypUFvVKNSPPCdqgSXIE9eJDD8LM= +github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= +github.com/olekukonko/tablewriter v1.1.3 h1:VSHhghXxrP0JHl+0NnKid7WoEmd9/urKRJLysb70nnA= +github.com/olekukonko/tablewriter v1.1.3/go.mod h1:9VU0knjhmMkXjnMKrZ3+L2JhhtsQ/L38BbL3CRNE8tM= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= @@ -196,10 +236,15 @@ github.com/quic-go/quic-go v0.63.0 h1:LIFGHI4PFUhhw2dDD1ARHdCff143ffMHwZtbnbuJ78 github.com/quic-go/quic-go v0.63.0/go.mod h1:RAro2j2yN9a9EiPACLHT9IB2NXCvGQmmo/alT0yYI0w= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil/v4 v4.26.6 h1:Mzr/npDtQC/xpeEuQKHZt8Zo9CmPvhTj8nkR8w5TLDs= github.com/shirou/gopsutil/v4 v4.26.6/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -234,6 +279,10 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= +github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0= +github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= go.mongodb.org/mongo-driver/v2 v2.9.1 h1:jewiFs2m1/VOQp8qhFshX6hWZ+EAXDhZHXExAUMcOgQ= go.mongodb.org/mongo-driver/v2 v2.9.1/go.mod h1:SHKN0IWkKmEVGHLjXnni6s4wPKX4v86FTgOeJJFuXcA= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= @@ -277,6 +326,8 @@ golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= +golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -324,6 +375,8 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= +golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 8c7f9aaf5a197fd9ccb1b32a5707cea935b9470c Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 18:57:31 +0200 Subject: [PATCH 02/10] Introduce db.Tx to keep *gorm.DB out of the public API Wrap the ORM transaction in a concrete Tx type so the *Tx facade methods and Publisher.PublishTx no longer expose *gorm.DB. GORM remains the backend and the generated SQL is unchanged. --- internal/api/v2/v2.go | 7 +++---- internal/checker/maintenance.go | 3 +-- internal/db/db.go | 28 ++++++++++++++-------------- internal/db/notification.go | 16 ++++++++-------- internal/db/tx.go | 9 +++++++++ internal/notification/publisher.go | 4 +--- tests/db_tx_test.go | 19 +++++++++++++------ 7 files changed, 49 insertions(+), 37 deletions(-) create mode 100644 internal/db/tx.go diff --git a/internal/api/v2/v2.go b/internal/api/v2/v2.go index 2358cf0..123c553 100644 --- a/internal/api/v2/v2.go +++ b/internal/api/v2/v2.go @@ -11,7 +11,6 @@ import ( "github.com/gin-gonic/gin" "go.uber.org/zap" - "gorm.io/gorm" apiErrors "github.com/stackmon/otc-status-dashboard/internal/api/errors" "github.com/stackmon/otc-status-dashboard/internal/api/rbac" @@ -966,7 +965,7 @@ func validateEventCreationTimes(incData IncidentData) error { func createEvent(dbInst *db.DB, log *zap.Logger, inc *db.Incident, userID *string, pub *notification.Publisher) error { log.Info("start to save an event to the database") - err := dbInst.WithTx(context.Background(), func(tx *gorm.DB) error { + err := dbInst.WithTx(context.Background(), func(tx *db.Tx) error { id, err := dbInst.SaveIncidentTx(tx, inc) if err != nil { return err @@ -1038,7 +1037,7 @@ func optionalPublisher(pub []*notification.Publisher) *notification.Publisher { // publishMaintenanceChange enqueues notification rows for a committed maintenance // change inside tx. It is a no-op for non-maintenance events or a disabled publisher. func publishMaintenanceChange( - ctx context.Context, tx *gorm.DB, pub *notification.Publisher, + ctx context.Context, tx *db.Tx, pub *notification.Publisher, inc *db.Incident, oldStatus event.Status, userID *string, ) error { if !pub.Enabled() || inc.Type != event.TypeMaintenance { @@ -1071,7 +1070,7 @@ func persistIncidentPatch( storedIncident *db.Incident, oldStatus event.Status, userID *string, ) bool { statusChanged := storedIncident.Status != oldStatus - err := dbInst.WithTx(c.Request.Context(), func(tx *gorm.DB) error { + err := dbInst.WithTx(c.Request.Context(), func(tx *db.Tx) error { if e := dbInst.ModifyIncidentTx(tx, storedIncident); e != nil { return e } diff --git a/internal/checker/maintenance.go b/internal/checker/maintenance.go index 5279ced..48e1e26 100644 --- a/internal/checker/maintenance.go +++ b/internal/checker/maintenance.go @@ -7,7 +7,6 @@ import ( "time" "go.uber.org/zap" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/db" "github.com/stackmon/otc-status-dashboard/internal/event" @@ -123,7 +122,7 @@ func (ch *Checker) processMaintenance(mn *db.Incident, activeMaintenances *[]uin mn.Status = actualStatus // The modify + enqueue share one transaction: on a version conflict the // whole thing rolls back and no notification is published. - txErr := ch.db.WithTx(context.Background(), func(tx *gorm.DB) error { + txErr := ch.db.WithTx(context.Background(), func(tx *db.Tx) error { if modErr := ch.db.ModifyIncidentTx(tx, mn); modErr != nil { return modErr } diff --git a/internal/db/db.go b/internal/db/db.go index 5e0b93e..49fbf4d 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -269,27 +269,27 @@ func (db *DB) GetIncident(id int) (*Incident, error) { // WithTx runs fn inside a single transaction on the shared connection pool. // Callers use it to write a business change and enqueue its notification atomically. -func (db *DB) WithTx(ctx context.Context, fn func(tx *gorm.DB) error) error { - return db.g.WithContext(ctx).Transaction(func(tx *gorm.DB) error { - return fn(tx) +func (db *DB) WithTx(ctx context.Context, fn func(tx *Tx) error) error { + return db.g.WithContext(ctx).Transaction(func(gtx *gorm.DB) error { + return fn(&Tx{g: gtx}) }) } // SaveIncidentTx creates an incident using the provided transaction. -func (db *DB) SaveIncidentTx(tx *gorm.DB, inc *Incident) (uint, error) { - if err := tx.Create(inc).Error; err != nil { +func (db *DB) SaveIncidentTx(tx *Tx, inc *Incident) (uint, error) { + if err := tx.g.Create(inc).Error; err != nil { return 0, err } return inc.ID, nil } func (db *DB) SaveIncident(inc *Incident) (uint, error) { - return db.SaveIncidentTx(db.g, inc) + return db.SaveIncidentTx(&Tx{g: db.g}, inc) } // ModifyIncidentTx applies a modification (with maintenance optimistic locking and // new status inserts) using the provided transaction. -func (db *DB) ModifyIncidentTx(tx *gorm.DB, inc *Incident) error { +func (db *DB) ModifyIncidentTx(tx *Tx, inc *Incident) error { if inc.Version == nil { return errors.New("version is required for event modification") } @@ -298,7 +298,7 @@ func (db *DB) ModifyIncidentTx(tx *gorm.DB, inc *Incident) error { newVersion := expectedVersion + 1 inc.Version = &newVersion - query := tx.Model(&Incident{}).Where("id = ?", inc.ID) + query := tx.g.Model(&Incident{}).Where("id = ?", inc.ID) if inc.Type == event.TypeMaintenance { query = query.Where("version = ?", expectedVersion) @@ -321,7 +321,7 @@ func (db *DB) ModifyIncidentTx(tx *gorm.DB, inc *Incident) error { if inc.Statuses[i].IncidentID == 0 { inc.Statuses[i].IncidentID = inc.ID } - if err := tx.Create(&inc.Statuses[i]).Error; err != nil { + if err := tx.g.Create(&inc.Statuses[i]).Error; err != nil { return err } } @@ -330,8 +330,8 @@ func (db *DB) ModifyIncidentTx(tx *gorm.DB, inc *Incident) error { } func (db *DB) ModifyIncident(inc *Incident) error { - return db.g.Transaction(func(tx *gorm.DB) error { - return db.ModifyIncidentTx(tx, inc) + return db.g.Transaction(func(gtx *gorm.DB) error { + return db.ModifyIncidentTx(&Tx{g: gtx}, inc) }) } @@ -814,10 +814,10 @@ func (db *DB) GetEventUpdates(incidentID uint) ([]IncidentStatus, error) { // ModifyEventUpdateTx patches an event status update's text using the provided // transaction and returns the updated row. -func (db *DB) ModifyEventUpdateTx(tx *gorm.DB, update IncidentStatus) (IncidentStatus, error) { +func (db *DB) ModifyEventUpdateTx(tx *Tx, update IncidentStatus) (IncidentStatus, error) { now := time.Now().UTC() var updated IncidentStatus - r := tx.Model(&IncidentStatus{}). + r := tx.g.Model(&IncidentStatus{}). Clauses(clause.Returning{}). Where("id = ? AND incident_id = ?", update.ID, update.IncidentID). Updates(map[string]interface{}{ @@ -837,5 +837,5 @@ func (db *DB) ModifyEventUpdateTx(tx *gorm.DB, update IncidentStatus) (IncidentS } func (db *DB) ModifyEventUpdate(update IncidentStatus) (IncidentStatus, error) { - return db.ModifyEventUpdateTx(db.g, update) + return db.ModifyEventUpdateTx(&Tx{g: db.g}, update) } diff --git a/internal/db/notification.go b/internal/db/notification.go index d674891..6f53fa6 100644 --- a/internal/db/notification.go +++ b/internal/db/notification.go @@ -44,7 +44,7 @@ func (db *DB) rowExists(tx *gorm.DB, dedupKey string) (bool, error) { // Enqueue inserts one outbox row for a single recipient. // The row must be written in the same DB transaction as the business change. -func (db *DB) Enqueue(ctx context.Context, tx *gorm.DB, row NotificationOutbox) error { +func (db *DB) Enqueue(ctx context.Context, tx *Tx, row NotificationOutbox) error { if row.DedupKey == "" { return errors.New("notification: dedup_key is required") } @@ -65,7 +65,7 @@ func (db *DB) Enqueue(ctx context.Context, tx *gorm.DB, row NotificationOutbox) // It must use `FOR UPDATE SKIP LOCKED` semantics and mark rows as processing, // increment attempts, and store lease metadata. func (db *DB) ClaimPending( - ctx context.Context, tx *gorm.DB, limit int, leaseOwner string, _ time.Duration, + ctx context.Context, tx *Tx, limit int, leaseOwner string, _ time.Duration, ) ([]NotificationOutbox, error) { var rows []NotificationOutbox @@ -98,7 +98,7 @@ func (db *DB) ClaimPending( } // MarkSent marks a row as sent and clears the active lease. -func (db *DB) MarkSent(ctx context.Context, tx *gorm.DB, id uint) error { +func (db *DB) MarkSent(ctx context.Context, tx *Tx, id uint) error { return db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { res := gtx.Model(&NotificationOutbox{}). Where("id = ?", id).Updates(map[string]any{ @@ -138,7 +138,7 @@ func (db *DB) getRowByID(tx *gorm.DB, id uint) (*NotificationOutbox, error) { // If retries remain, keep status='pending' and set next_attempt_at. // Otherwise set status='failed' and last_error. func (db *DB) MarkFailed( - ctx context.Context, tx *gorm.DB, id uint, errText string, maxAttempts int, backoff func(attempts int) time.Time, + ctx context.Context, tx *Tx, id uint, errText string, maxAttempts int, backoff func(attempts int) time.Time, ) error { return db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { row, err := db.getRowByID(gtx, id) @@ -166,7 +166,7 @@ func (db *DB) MarkFailed( // MarkFailedTerminal fails a row outright, ignoring the remaining attempts. Used for // rejections the server will repeat on every retry, such as an unknown recipient. -func (db *DB) MarkFailedTerminal(ctx context.Context, tx *gorm.DB, id uint, errText string) error { +func (db *DB) MarkFailedTerminal(ctx context.Context, tx *Tx, id uint, errText string) error { return db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { res := gtx.Model(&NotificationOutbox{}). Where("id = ?", id).Updates(map[string]any{ @@ -189,7 +189,7 @@ func (db *DB) MarkFailedTerminal(ctx context.Context, tx *gorm.DB, id uint, errT // RecoverStaleProcessing returns stale processing rows back to pending, // or marks them failed if they exhausted all attempts. func (db *DB) RecoverStaleProcessing( - ctx context.Context, tx *gorm.DB, leaseTimeout time.Duration, maxAttempts int, + ctx context.Context, tx *Tx, leaseTimeout time.Duration, maxAttempts int, ) ([]NotificationOutbox, error) { var rows []NotificationOutbox @@ -230,9 +230,9 @@ func (db *DB) RecoverStaleProcessing( } // execWithTx runs the callback in a transaction if tx is nil; otherwise it uses the provided tx. -func (db *DB) execWithTx(ctx context.Context, tx *gorm.DB, fn func(*gorm.DB) error) error { +func (db *DB) execWithTx(ctx context.Context, tx *Tx, fn func(*gorm.DB) error) error { if tx != nil { - return fn(tx) + return fn(tx.g) } return db.g.WithContext(ctx).Transaction(func(gtx *gorm.DB) error { diff --git a/internal/db/tx.go b/internal/db/tx.go new file mode 100644 index 0000000..45cf64c --- /dev/null +++ b/internal/db/tx.go @@ -0,0 +1,9 @@ +package db + +import "gorm.io/gorm" + +// Tx wraps the underlying ORM transaction. Callers pass it through to the +// *Tx facade methods and PublishTx; they never call methods on it directly. +type Tx struct { + g *gorm.DB +} diff --git a/internal/notification/publisher.go b/internal/notification/publisher.go index 8999072..e11af11 100644 --- a/internal/notification/publisher.go +++ b/internal/notification/publisher.go @@ -4,8 +4,6 @@ import ( "context" "errors" - "gorm.io/gorm" - "github.com/stackmon/otc-status-dashboard/internal/db" ) @@ -77,7 +75,7 @@ func (p *Publisher) Enabled() bool { // PublishTx enqueues one outbox row per recipient for the change, using tx so the // rows share the business transaction. It is a no-op when disabled or when the // change resolves to no recipients. -func (p *Publisher) PublishTx(ctx context.Context, tx *gorm.DB, ch Change) error { +func (p *Publisher) PublishTx(ctx context.Context, tx *db.Tx, ch Change) error { if !p.Enabled() { return nil } diff --git a/tests/db_tx_test.go b/tests/db_tx_test.go index a99083a..fcc2913 100644 --- a/tests/db_tx_test.go +++ b/tests/db_tx_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/db" "github.com/stackmon/otc-status-dashboard/internal/event" @@ -19,7 +18,7 @@ func TestWithTx_CommitsIncidentAndOutboxAtomically(t *testing.T) { d, g := newNotifDB(t) var incID uint - err := d.WithTx(ctx, func(tx *gorm.DB) error { + err := d.WithTx(ctx, func(tx *db.Tx) error { id, e := d.SaveIncidentTx(tx, newMaintenanceIncident()) if e != nil { return e @@ -43,7 +42,7 @@ func TestWithTx_RollsBackBothOnError(t *testing.T) { var incID uint var dedup string - err := d.WithTx(ctx, func(tx *gorm.DB) error { + err := d.WithTx(ctx, func(tx *db.Tx) error { id, e := d.SaveIncidentTx(tx, newMaintenanceIncident()) if e != nil { return e @@ -75,7 +74,7 @@ func TestModifyIncidentTx_SharedTxWithEnqueue(t *testing.T) { inc.Status = event.MaintenanceReviewed row := newOutboxRow(incID, "creator@com.com") - err = d.WithTx(ctx, func(tx *gorm.DB) error { + err = d.WithTx(ctx, func(tx *db.Tx) error { if e := d.ModifyIncidentTx(tx, inc); e != nil { return e } @@ -100,8 +99,16 @@ func TestModifyEventUpdateTx_UpdatesText(t *testing.T) { status := db.IncidentStatus{IncidentID: incID, Status: event.MaintenancePendingReview, Text: "original"} require.NoError(t, g.Create(&status).Error) - updated, err := d.ModifyEventUpdateTx(g, db.IncidentStatus{ - ID: status.ID, IncidentID: incID, Text: "patched", + var updated db.IncidentStatus + err := d.WithTx(context.Background(), func(tx *db.Tx) error { + u, e := d.ModifyEventUpdateTx(tx, db.IncidentStatus{ + ID: status.ID, IncidentID: incID, Text: "patched", + }) + if e != nil { + return e + } + updated = u + return nil }) require.NoError(t, err) assert.Equal(t, "patched", updated.Text) From 05bf2981cfde6ff5c608c884d7700f69f9d8a834 Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 20:38:50 +0200 Subject: [PATCH 03/10] Replace the GORM backend with Ent for event and component reads and writes The facade keeps its signatures and domain structs; Ent entities stay inside internal/db behind mapper functions. Transactional, locked and outbox paths still run on GORM and move in a later step. Verified against a restored production copy: the read and write paths return the same rows and fields as before, apart from result ordering, which is now stable instead of following physical order. --- ent/incident.go | 33 ++-- ent/incident_create.go | 6 +- ent/incidentstatus.go | 22 ++- ent/incidentstatus_create.go | 4 +- ent/mutation.go | 10 +- ent/schema/incident.go | 6 +- ent/schema/incidentstatus.go | 4 +- internal/db/db.go | 373 +++++++++++++++++++++++++---------- internal/db/event_types.go | 45 +++++ internal/db/info.go | 23 +-- internal/db/maintenances.go | 23 +-- internal/db/mappers.go | 152 ++++++++++++++ internal/db/mock.go | 7 +- tests/main_test.go | 28 ++- 14 files changed, 549 insertions(+), 187 deletions(-) create mode 100644 internal/db/event_types.go create mode 100644 internal/db/mappers.go diff --git a/ent/incident.go b/ent/incident.go index 6ea762d..4e7c39a 100644 --- a/ent/incident.go +++ b/ent/incident.go @@ -20,7 +20,7 @@ type Incident struct { // Text holds the value of the "text" field. Text string `json:"text,omitempty"` // Description holds the value of the "description" field. - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` // StartDate holds the value of the "start_date" field. StartDate time.Time `json:"start_date,omitempty"` // EndDate holds the value of the "end_date" field. @@ -40,9 +40,9 @@ type Incident struct { // DeletedAt holds the value of the "deleted_at" field. DeletedAt time.Time `json:"deleted_at,omitempty"` // CreatedBy holds the value of the "created_by" field. - CreatedBy string `json:"created_by,omitempty"` + CreatedBy *string `json:"created_by,omitempty"` // ContactEmail holds the value of the "contact_email" field. - ContactEmail string `json:"contact_email,omitempty"` + ContactEmail *string `json:"contact_email,omitempty"` // Version holds the value of the "version" field. Version int `json:"version,omitempty"` // Edges holds the relations/edges for other nodes in the graph. @@ -124,7 +124,8 @@ func (_m *Incident) assignValues(columns []string, values []any) error { if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field description", values[i]) } else if value.Valid { - _m.Description = value.String + _m.Description = new(string) + *_m.Description = value.String } case incident.FieldStartDate: if value, ok := values[i].(*sql.NullTime); !ok { @@ -184,13 +185,15 @@ func (_m *Incident) assignValues(columns []string, values []any) error { if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field created_by", values[i]) } else if value.Valid { - _m.CreatedBy = value.String + _m.CreatedBy = new(string) + *_m.CreatedBy = value.String } case incident.FieldContactEmail: if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field contact_email", values[i]) } else if value.Valid { - _m.ContactEmail = value.String + _m.ContactEmail = new(string) + *_m.ContactEmail = value.String } case incident.FieldVersion: if value, ok := values[i].(*sql.NullInt64); !ok { @@ -247,8 +250,10 @@ func (_m *Incident) String() string { builder.WriteString("text=") builder.WriteString(_m.Text) builder.WriteString(", ") - builder.WriteString("description=") - builder.WriteString(_m.Description) + if v := _m.Description; v != nil { + builder.WriteString("description=") + builder.WriteString(*v) + } builder.WriteString(", ") builder.WriteString("start_date=") builder.WriteString(_m.StartDate.Format(time.ANSIC)) @@ -277,11 +282,15 @@ func (_m *Incident) String() string { builder.WriteString("deleted_at=") builder.WriteString(_m.DeletedAt.Format(time.ANSIC)) builder.WriteString(", ") - builder.WriteString("created_by=") - builder.WriteString(_m.CreatedBy) + if v := _m.CreatedBy; v != nil { + builder.WriteString("created_by=") + builder.WriteString(*v) + } builder.WriteString(", ") - builder.WriteString("contact_email=") - builder.WriteString(_m.ContactEmail) + if v := _m.ContactEmail; v != nil { + builder.WriteString("contact_email=") + builder.WriteString(*v) + } builder.WriteString(", ") builder.WriteString("version=") builder.WriteString(fmt.Sprintf("%v", _m.Version)) diff --git a/ent/incident_create.go b/ent/incident_create.go index b0164d2..c1e6138 100644 --- a/ent/incident_create.go +++ b/ent/incident_create.go @@ -338,7 +338,7 @@ func (_c *IncidentCreate) createSpec() (*Incident, *sqlgraph.CreateSpec) { } if value, ok := _c.mutation.Description(); ok { _spec.SetField(incident.FieldDescription, field.TypeString, value) - _node.Description = value + _node.Description = &value } if value, ok := _c.mutation.StartDate(); ok { _spec.SetField(incident.FieldStartDate, field.TypeTime, value) @@ -378,11 +378,11 @@ func (_c *IncidentCreate) createSpec() (*Incident, *sqlgraph.CreateSpec) { } if value, ok := _c.mutation.CreatedBy(); ok { _spec.SetField(incident.FieldCreatedBy, field.TypeString, value) - _node.CreatedBy = value + _node.CreatedBy = &value } if value, ok := _c.mutation.ContactEmail(); ok { _spec.SetField(incident.FieldContactEmail, field.TypeString, value) - _node.ContactEmail = value + _node.ContactEmail = &value } if value, ok := _c.mutation.Version(); ok { _spec.SetField(incident.FieldVersion, field.TypeInt, value) diff --git a/ent/incidentstatus.go b/ent/incidentstatus.go index b547839..cbf6735 100644 --- a/ent/incidentstatus.go +++ b/ent/incidentstatus.go @@ -32,9 +32,9 @@ type IncidentStatus struct { // DeletedAt holds the value of the "deleted_at" field. DeletedAt time.Time `json:"deleted_at,omitempty"` // CreatedBy holds the value of the "created_by" field. - CreatedBy string `json:"created_by,omitempty"` + CreatedBy *string `json:"created_by,omitempty"` // ModifiedBy holds the value of the "modified_by" field. - ModifiedBy string `json:"modified_by,omitempty"` + ModifiedBy *string `json:"modified_by,omitempty"` selectValues sql.SelectValues } @@ -116,13 +116,15 @@ func (_m *IncidentStatus) assignValues(columns []string, values []any) error { if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field created_by", values[i]) } else if value.Valid { - _m.CreatedBy = value.String + _m.CreatedBy = new(string) + *_m.CreatedBy = value.String } case incidentstatus.FieldModifiedBy: if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field modified_by", values[i]) } else if value.Valid { - _m.ModifiedBy = value.String + _m.ModifiedBy = new(string) + *_m.ModifiedBy = value.String } default: _m.selectValues.Set(columns[i], values[i]) @@ -181,11 +183,15 @@ func (_m *IncidentStatus) String() string { builder.WriteString("deleted_at=") builder.WriteString(_m.DeletedAt.Format(time.ANSIC)) builder.WriteString(", ") - builder.WriteString("created_by=") - builder.WriteString(_m.CreatedBy) + if v := _m.CreatedBy; v != nil { + builder.WriteString("created_by=") + builder.WriteString(*v) + } builder.WriteString(", ") - builder.WriteString("modified_by=") - builder.WriteString(_m.ModifiedBy) + if v := _m.ModifiedBy; v != nil { + builder.WriteString("modified_by=") + builder.WriteString(*v) + } builder.WriteByte(')') return builder.String() } diff --git a/ent/incidentstatus_create.go b/ent/incidentstatus_create.go index 0b920ec..4616cff 100644 --- a/ent/incidentstatus_create.go +++ b/ent/incidentstatus_create.go @@ -246,11 +246,11 @@ func (_c *IncidentStatusCreate) createSpec() (*IncidentStatus, *sqlgraph.CreateS } if value, ok := _c.mutation.CreatedBy(); ok { _spec.SetField(incidentstatus.FieldCreatedBy, field.TypeString, value) - _node.CreatedBy = value + _node.CreatedBy = &value } if value, ok := _c.mutation.ModifiedBy(); ok { _spec.SetField(incidentstatus.FieldModifiedBy, field.TypeString, value) - _node.ModifiedBy = value + _node.ModifiedBy = &value } return _node, _spec } diff --git a/ent/mutation.go b/ent/mutation.go index 68ee753..f6d526a 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -1475,7 +1475,7 @@ func (m *IncidentMutation) Description() (r string, exists bool) { // OldDescription returns the old "description" field's value of the Incident entity. // If the Incident 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 *IncidentMutation) OldDescription(ctx context.Context) (v string, err error) { +func (m *IncidentMutation) OldDescription(ctx context.Context) (v *string, err error) { if !m.op.Is(OpUpdateOne) { return v, errors.New("OldDescription is only allowed on UpdateOne operations") } @@ -1933,7 +1933,7 @@ func (m *IncidentMutation) CreatedBy() (r string, exists bool) { // OldCreatedBy returns the old "created_by" field's value of the Incident entity. // If the Incident 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 *IncidentMutation) OldCreatedBy(ctx context.Context) (v string, err error) { +func (m *IncidentMutation) OldCreatedBy(ctx context.Context) (v *string, err error) { if !m.op.Is(OpUpdateOne) { return v, errors.New("OldCreatedBy is only allowed on UpdateOne operations") } @@ -1982,7 +1982,7 @@ func (m *IncidentMutation) ContactEmail() (r string, exists bool) { // OldContactEmail returns the old "contact_email" field's value of the Incident entity. // If the Incident 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 *IncidentMutation) OldContactEmail(ctx context.Context) (v string, err error) { +func (m *IncidentMutation) OldContactEmail(ctx context.Context) (v *string, err error) { if !m.op.Is(OpUpdateOne) { return v, errors.New("OldContactEmail is only allowed on UpdateOne operations") } @@ -3186,7 +3186,7 @@ func (m *IncidentStatusMutation) CreatedBy() (r string, exists bool) { // OldCreatedBy returns the old "created_by" field's value of the IncidentStatus entity. // If the IncidentStatus 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 *IncidentStatusMutation) OldCreatedBy(ctx context.Context) (v string, err error) { +func (m *IncidentStatusMutation) OldCreatedBy(ctx context.Context) (v *string, err error) { if !m.op.Is(OpUpdateOne) { return v, errors.New("OldCreatedBy is only allowed on UpdateOne operations") } @@ -3235,7 +3235,7 @@ func (m *IncidentStatusMutation) ModifiedBy() (r string, exists bool) { // OldModifiedBy returns the old "modified_by" field's value of the IncidentStatus entity. // If the IncidentStatus 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 *IncidentStatusMutation) OldModifiedBy(ctx context.Context) (v string, err error) { +func (m *IncidentStatusMutation) OldModifiedBy(ctx context.Context) (v *string, err error) { if !m.op.Is(OpUpdateOne) { return v, errors.New("OldModifiedBy is only allowed on UpdateOne operations") } diff --git a/ent/schema/incident.go b/ent/schema/incident.go index 58e6dde..b37f0b6 100644 --- a/ent/schema/incident.go +++ b/ent/schema/incident.go @@ -25,7 +25,7 @@ func (Incident) Fields() []ent.Field { field.Int("id"). SchemaType(map[string]string{"postgres": "serial"}), field.String("text").NotEmpty(), - field.String("description").Optional(). + field.String("description").Optional().Nillable(). SchemaType(map[string]string{"postgres": "varchar(1500)"}), field.Time("start_date"). SchemaType(map[string]string{"postgres": "timestamp"}), @@ -45,9 +45,9 @@ func (Incident) Fields() []ent.Field { SchemaType(map[string]string{"postgres": "timestamp"}), field.Time("deleted_at").Optional(). SchemaType(map[string]string{"postgres": "timestamp"}), - field.String("created_by").Optional(). + field.String("created_by").Optional().Nillable(). SchemaType(map[string]string{"postgres": "varchar(255)"}), - field.String("contact_email").Optional(). + field.String("contact_email").Optional().Nillable(). SchemaType(map[string]string{"postgres": "varchar(255)"}), field.Int("version").Default(1). SchemaType(map[string]string{"postgres": "integer"}), diff --git a/ent/schema/incidentstatus.go b/ent/schema/incidentstatus.go index 59cf9a0..d21dc8d 100644 --- a/ent/schema/incidentstatus.go +++ b/ent/schema/incidentstatus.go @@ -38,9 +38,9 @@ func (IncidentStatus) Fields() []ent.Field { SchemaType(map[string]string{"postgres": "timestamp"}), field.Time("deleted_at").Optional(). SchemaType(map[string]string{"postgres": "timestamp"}), - field.String("created_by").Optional(). + field.String("created_by").Optional().Nillable(). SchemaType(map[string]string{"postgres": "varchar(255)"}), - field.String("modified_by").Optional(). + field.String("modified_by").Optional().Nillable(). SchemaType(map[string]string{"postgres": "varchar(255)"}), } } diff --git a/internal/db/db.go b/internal/db/db.go index 49fbf4d..8b25b62 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -6,12 +6,19 @@ import ( "fmt" "time" + "entgo.io/ent/dialect" + entsql "entgo.io/ent/dialect/sql" "go.uber.org/zap" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/clause" "moul.io/zapgorm2" + "github.com/stackmon/otc-status-dashboard/ent" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/componentattr" + "github.com/stackmon/otc-status-dashboard/ent/incident" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" "github.com/stackmon/otc-status-dashboard/internal/conf" "github.com/stackmon/otc-status-dashboard/internal/event" ) @@ -26,8 +33,11 @@ const ( dbConnMaxIdleTime = 30 * time.Second ) +// DB is the storage facade. Both ORMs share one connection pool: methods that +// have been migrated run on Ent, the rest still run on GORM. type DB struct { g *gorm.DB + e *ent.Client } func New(c *conf.Config) (*DB, error) { @@ -61,7 +71,9 @@ func New(c *conf.Config) (*DB, error) { sqlDB.SetConnMaxLifetime(dbConnMaxLifetime) sqlDB.SetConnMaxIdleTime(dbConnMaxIdleTime) - return &DB{g: g}, nil + e := ent.NewClient(ent.Driver(entsql.OpenDB(dialect.Postgres, sqlDB))) + + return &DB{g: g, e: e}, nil } func (db *DB) Close() error { @@ -244,27 +256,30 @@ func (db *DB) GetEventsInternal(params ...*IncidentsParams) ([]*Incident, error) } func (db *DB) GetIncident(id int) (*Incident, error) { - inc := Incident{ID: uint(id)} + ctx := context.Background() - r := db.g.Model(&Incident{}). - Where(inc). - Preload("Statuses", func(db *gorm.DB) *gorm.DB { - return db.Order("id ASC") - }). - Preload("Components", func(db *gorm.DB) *gorm.DB { - return db.Select("ID, Name") + e, err := db.e.Incident.Query(). + Where(incident.IDEQ(id)). + WithComponents(func(q *ent.ComponentQuery) { + q.Select(component.FieldID, component.FieldName) + q.WithAttributes() }). - Preload("Components.Attrs"). - First(&inc) - - if r.Error != nil { - if errors.Is(r.Error, gorm.ErrRecordNotFound) { + First(ctx) + if err != nil { + if ent.IsNotFound(err) { return nil, ErrDBIncidentDSNotExist } - return nil, r.Error + return nil, err + } + + inc := incidentFromEnt(e) + grouped, err := db.statusesByIncident(ctx, []int{e.ID}) + if err != nil { + return nil, err } + attachStatuses([]*Incident{inc}, grouped) - return &inc, nil + return inc, nil } // WithTx runs fn inside a single transaction on the shared connection pool. @@ -383,14 +398,13 @@ func (db *DB) AddComponentToIncident(inc *Incident, comp *Component, status Inci // ReOpenIncident the special function if you need to NULL your end_date. func (db *DB) ReOpenIncident(inc *Incident) error { - r := db.g.Model(&Incident{}).Where("id = ?", inc.ID).Updates(map[string]interface{}{ - "end_date": nil, - }) - if r.Error != nil { - return r.Error + err := db.e.Incident.UpdateOneID(int(inc.ID)). + ClearEndDate(). + Exec(context.Background()) + if ent.IsNotFound(err) { + return nil } - - return nil + return err } // GetEventsByComponentID retrieves all public events associated with a specific component ID. @@ -490,56 +504,61 @@ func (db *DB) GetIncidentsByComponentAttr(attr *ComponentAttr, params ...*Incide return incidents, nil } -func (db *DB) GetOpenedIncidentsWithComponent(name string, attrs []ComponentAttr) (*Incident, error) { - comp := &Component{Name: name, Attrs: attrs} - r := db.g.Model(&Component{}).Preload("Attrs").Find(comp) - if r.Error != nil { - if errors.Is(r.Error, gorm.ErrRecordNotFound) { - return nil, ErrDBComponentDSNotExist - } - return nil, r.Error +func (db *DB) GetOpenedIncidentsWithComponent(_ string, _ []ComponentAttr) (*Incident, error) { + ctx := context.Background() + + // Legacy behaviour kept as-is: the component probe is not restricted to any + // name or attribute and the incident lookup carries no component filter, so + // this returns an arbitrary open incident. + if _, err := db.e.Component.Query().Exist(ctx); err != nil { + return nil, err } - var incident Incident - r = db.g.Model(&Incident{}). - Preload("Statuses"). - Preload("Components", func(db *gorm.DB) *gorm.DB { - return db.Select("ID") + e, err := db.e.Incident.Query(). + WithComponents(func(q *ent.ComponentQuery) { + q.Select(component.FieldID) }). - // Where("component_id = ?", comp.ID). - First(&incident) + Order(incident.ByID(entsql.OrderAsc())). + First(ctx) + if err != nil { + return nil, err + } - if r.Error != nil { - return nil, r.Error + inc := incidentFromEnt(e) + grouped, err := db.statusesByIncident(ctx, []int{e.ID}) + if err != nil { + return nil, err } + attachStatuses([]*Incident{inc}, grouped) - return &incident, nil + return inc, nil } func (db *DB) GetComponent(id int) (*Component, error) { - comp := &Component{ID: uint(id)} - r := db.g.Model(&Component{}).Preload("Attrs").First(comp) - - if r.Error != nil { - if errors.Is(r.Error, gorm.ErrRecordNotFound) { + e, err := db.e.Component.Query(). + Where(component.IDEQ(id)). + WithAttributes(). + First(context.Background()) + if err != nil { + if ent.IsNotFound(err) { return nil, ErrDBComponentDSNotExist } - return nil, r.Error + return nil, err } - return comp, nil + comp := componentFromEnt(e) + return &comp, nil } func (db *DB) GetComponentsAsMap() (map[int]*Component, error) { - var components []Component - r := db.g.Model(&Component{}).Find(&components) - - if r.Error != nil { - return nil, r.Error + rows, err := db.e.Component.Query().All(context.Background()) + if err != nil { + return nil, err } - var compMap = make(map[int]*Component) - for _, comp := range components { + compMap := make(map[int]*Component, len(rows)) + for _, row := range rows { + comp := componentFromEnt(row) compMap[int(comp.ID)] = &comp } @@ -547,22 +566,47 @@ func (db *DB) GetComponentsAsMap() (map[int]*Component, error) { } func (db *DB) GetComponentsWithValues() ([]Component, error) { - var components []Component - r := db.g.Model(&Component{}).Preload("Attrs").Find(&components) + rows, err := db.e.Component.Query(). + WithAttributes(). + All(context.Background()) + if err != nil { + return nil, err + } - if r.Error != nil { - return nil, r.Error + components := make([]Component, 0, len(rows)) + for _, row := range rows { + components = append(components, componentFromEnt(row)) } return components, nil } func (db *DB) GetComponentsWithIncidents() ([]Component, error) { - var components []Component - r := db.g.Model(&Component{}).Preload("Attrs").Preload("Incidents").Preload("Incidents.Statuses").Find(&components) + ctx := context.Background() - if r.Error != nil { - return nil, r.Error + rows, err := db.e.Component.Query(). + WithAttributes(). + WithIncidents(). + All(ctx) + if err != nil { + return nil, err + } + + var entIncidents []*ent.Incident + for _, row := range rows { + entIncidents = append(entIncidents, row.Edges.Incidents...) + } + + grouped, err := db.statusesByIncident(ctx, incidentIDs(entIncidents)) + if err != nil { + return nil, err + } + + components := make([]Component, 0, len(rows)) + for _, row := range rows { + comp := componentFromEnt(row) + attachStatuses(comp.Incidents, grouped) + components = append(components, comp) } return components, nil @@ -570,44 +614,48 @@ func (db *DB) GetComponentsWithIncidents() ([]Component, error) { // GetComponentFromNameAttrs returns the Component from its name and region attribute. func (db *DB) GetComponentFromNameAttrs(name string, attr *ComponentAttr) (*Component, error) { - comp := Component{} - //nolint:lll - // You can reproduce this raw request - // select * from component join component_attribute ca on component.id=ca.component_id - // where component.id = - // (select component.id from component join component_attribute ca on component.id = ca.component_id and ca.value='EU-DE' and component.name='Cloud Container Engine'); - subQuery := db.g.Model(&Component{}). - Select("component.id"). - Joins("JOIN component_attribute ca ON ca.component_id = component.id"). - Where("ca.value = ?", attr.Value). - Where("component.name = ?", name) - r := db.g.Model(&Component{}).Where("name = ?", name). - Where("id = (?)", subQuery). - Preload("Attrs"). - First(&comp) - - if r.Error != nil { - if errors.Is(r.Error, gorm.ErrRecordNotFound) { + e, err := db.e.Component.Query(). + Where( + component.NameEQ(name), + component.HasAttributesWith(componentattr.ValueEQ(attr.Value)), + ). + WithAttributes(). + Order(component.ByID(entsql.OrderAsc())). + First(context.Background()) + if err != nil { + if ent.IsNotFound(err) { return nil, ErrDBComponentDSNotExist } - return nil, r.Error + return nil, err } + comp := componentFromEnt(e) return &comp, nil } func (db *DB) SaveComponent(comp *Component) (uint, error) { + ctx := context.Background() + // Validate required region attribute hasRegion := false for _, attr := range comp.Attrs { - if attr.Name == "region" { + if attr.Name == regionAttrName { hasRegion = true // Check if component with same name and region exists - var exists Component - if err := db.g.Joins("JOIN component_attribute ca ON ca.component_id = component.id"). - Where("component.name = ? AND ca.name = 'region' AND ca.value = ?", - comp.Name, attr.Value).First(&exists).Error; err == nil { + exists, err := db.e.Component.Query(). + Where( + component.NameEQ(comp.Name), + component.HasAttributesWith( + componentattr.NameEQ(regionAttrName), + componentattr.ValueEQ(attr.Value), + ), + ). + Exist(ctx) + if err != nil { + return 0, err + } + if exists { return 0, ErrDBComponentExists } break @@ -618,11 +666,48 @@ func (db *DB) SaveComponent(comp *Component) (uint, error) { return 0, fmt.Errorf("missing required region attribute") } - // Create the component - if err := db.g.Create(comp).Error; err != nil { + now := time.Now().UTC() + if comp.CreatedAt == nil { + comp.CreatedAt = &now + } + if comp.ModifiedAt == nil { + comp.ModifiedAt = &now + } + + tx, err := db.e.Tx(ctx) + if err != nil { return 0, err } + created, err := tx.Component.Create(). + SetName(comp.Name). + SetCreatedAt(*comp.CreatedAt). + SetModifiedAt(*comp.ModifiedAt). + Save(ctx) + if err != nil { + _ = tx.Rollback() + return 0, err + } + + for i := range comp.Attrs { + attr, attrErr := tx.ComponentAttr.Create(). + SetName(comp.Attrs[i].Name). + SetValue(comp.Attrs[i].Value). + SetComponentID(created.ID). + Save(ctx) + if attrErr != nil { + _ = tx.Rollback() + return 0, attrErr + } + comp.Attrs[i].ID = uint(attr.ID) + comp.Attrs[i].ComponentID = uint(created.ID) + } + + if err = tx.Commit(); err != nil { + return 0, err + } + + comp.ID = uint(created.ID) return comp.ID, nil } @@ -773,40 +858,116 @@ func (db *DB) IncreaseIncidentImpact(inc *Incident, impact int) (*Incident, erro Status: event.OutDatedSystem, Text: text, Timestamp: timeNow, + CreatedAt: &timeNow, + ModifiedAt: &timeNow, }) inc.Impact = &impact + inc.ModifiedAt = &timeNow - if r := db.g.Updates(inc); r.Error != nil { - return nil, r.Error + // Only non-zero fields are written for the incident row, mirroring the + // previous struct-based update. incident_status has no Ent edge, so the + // appended status row is inserted directly in the same transaction. + ctx := context.Background() + tx, err := db.e.Tx(ctx) + if err != nil { + return nil, err + } + + update := tx.Incident.UpdateOneID(int(inc.ID)) + if inc.Text != nil && *inc.Text != "" { + update.SetText(*inc.Text) + } + if inc.Description != nil { + update.SetDescription(*inc.Description) + } + if inc.StartDate != nil { + update.SetStartDate(*inc.StartDate) + } + if inc.EndDate != nil { + update.SetEndDate(*inc.EndDate) + } + update.SetImpact(*inc.Impact) + if inc.Status != "" { + update.SetStatus(string(inc.Status)) + } + if inc.System { + update.SetSystem(true) + } + if inc.Type != "" { + update.SetType(incident.Type(inc.Type)) + } + if inc.CreatedAt != nil { + update.SetCreatedAt(*inc.CreatedAt) + } + update.SetModifiedAt(timeNow) + if inc.CreatedBy != nil { + update.SetCreatedBy(*inc.CreatedBy) + } + if inc.ContactEmail != nil { + update.SetContactEmail(*inc.ContactEmail) + } + if inc.Version != nil { + update.SetVersion(*inc.Version) + } + + if err = update.Exec(ctx); err != nil { + _ = tx.Rollback() + return nil, err + } + + _, err = tx.IncidentStatus.Create(). + SetIncidentID(int(inc.ID)). + SetStatus(string(event.OutDatedSystem)). + SetText(text). + SetTimestamp(timeNow). + SetCreatedAt(timeNow). + SetModifiedAt(timeNow). + Save(ctx) + if err != nil { + _ = tx.Rollback() + return nil, err + } + + if err = tx.Commit(); err != nil { + return nil, err } return inc, nil } func (db *DB) GetUniqueAttributeValues(attrName string) ([]string, error) { - var values []string - r := db.g.Model(&ComponentAttr{}). - Select("DISTINCT value"). - Where("name = ?", attrName). - Order("value ASC"). - Pluck("value", &values) + rows, err := db.e.ComponentAttr.Query(). + Where(componentattr.NameEQ(attrName)). + Select(componentattr.FieldValue). + Order(componentattr.ByValue(entsql.OrderAsc())). + All(context.Background()) + if err != nil { + return nil, err + } - if r.Error != nil { - return nil, r.Error + values := make([]string, 0, len(rows)) + for i, row := range rows { + if i > 0 && rows[i-1].Value == row.Value { + continue + } + values = append(values, row.Value) } return values, nil } func (db *DB) GetEventUpdates(incidentID uint) ([]IncidentStatus, error) { - var updates []IncidentStatus - r := db.g.Model(&IncidentStatus{}). - Where("incident_id = ?", incidentID). - Order("id ASC"). - Find(&updates) + rows, err := db.e.IncidentStatus.Query(). + Where(incidentstatus.IncidentID(int(incidentID))). + Order(incidentstatus.ByID(entsql.OrderAsc())). + All(context.Background()) + if err != nil { + return nil, err + } - if r.Error != nil { - return nil, r.Error + updates := make([]IncidentStatus, 0, len(rows)) + for _, row := range rows { + updates = append(updates, incidentStatusFromEnt(row)) } return updates, nil diff --git a/internal/db/event_types.go b/internal/db/event_types.go new file mode 100644 index 0000000..ff99a8a --- /dev/null +++ b/internal/db/event_types.go @@ -0,0 +1,45 @@ +package db + +import ( + "context" + + entsql "entgo.io/ent/dialect/sql" + + "github.com/stackmon/otc-status-dashboard/ent" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/incident" +) + +// getEventsByType lists events of a single type with their update history. +func (db *DB) getEventsByType(eventType incident.Type, after uint, order entsql.OrderTermOption) ([]*Incident, error) { + ctx := context.Background() + + query := db.e.Incident.Query(). + Where(incident.TypeEQ(eventType)). + WithComponents(func(q *ent.ComponentQuery) { + q.Select(component.FieldID) + }). + Order(incident.ByID(order)) + + if after > 0 { + query = query.Where(incident.IDGTE(int(after))) + } + + rows, err := query.All(ctx) + if err != nil { + return nil, err + } + + incidents := make([]*Incident, 0, len(rows)) + for _, row := range rows { + incidents = append(incidents, incidentFromEnt(row)) + } + + grouped, err := db.statusesByIncident(ctx, incidentIDs(rows)) + if err != nil { + return nil, err + } + attachStatuses(incidents, grouped) + + return incidents, nil +} diff --git a/internal/db/info.go b/internal/db/info.go index d27c6c3..33a1aae 100644 --- a/internal/db/info.go +++ b/internal/db/info.go @@ -1,28 +1,11 @@ package db import ( - "gorm.io/gorm" + entsql "entgo.io/ent/dialect/sql" - "github.com/stackmon/otc-status-dashboard/internal/event" + "github.com/stackmon/otc-status-dashboard/ent/incident" ) func (db *DB) GetInfoEvents(after uint) ([]*Incident, error) { - var incidents []*Incident - - r := db.g.Model(&Incident{}). - Preload("Statuses"). - Preload("Components", func(db *gorm.DB) *gorm.DB { return db.Select("ID") }) - - r.Where("incident.type = ?", event.TypeInformation) - - if after > 0 { - r.Where("incident.id >= ?", after) - } - - r = r.Order("incident.id DESC") - - if err := r.Find(&incidents).Error; err != nil { - return nil, err - } - return incidents, nil + return db.getEventsByType(incident.TypeInfo, after, entsql.OrderDesc()) } diff --git a/internal/db/maintenances.go b/internal/db/maintenances.go index b0ab370..b29f6ac 100644 --- a/internal/db/maintenances.go +++ b/internal/db/maintenances.go @@ -1,28 +1,11 @@ package db import ( - "gorm.io/gorm" + entsql "entgo.io/ent/dialect/sql" - "github.com/stackmon/otc-status-dashboard/internal/event" + "github.com/stackmon/otc-status-dashboard/ent/incident" ) func (db *DB) GetMaintenances(after uint) ([]*Incident, error) { - var incidents []*Incident - - r := db.g.Model(&Incident{}). - Preload("Statuses"). - Preload("Components", func(db *gorm.DB) *gorm.DB { return db.Select("ID") }) - - r = r.Where("incident.type = ?", event.TypeMaintenance) - - if after > 0 { - r = r.Where("incident.id >= ?", after) - } - - r = r.Order("incident.id ASC") - - if err := r.Find(&incidents).Error; err != nil { - return nil, err - } - return incidents, nil + return db.getEventsByType(incident.TypeMaintenance, after, entsql.OrderAsc()) } diff --git a/internal/db/mappers.go b/internal/db/mappers.go new file mode 100644 index 0000000..7b2d318 --- /dev/null +++ b/internal/db/mappers.go @@ -0,0 +1,152 @@ +package db + +import ( + "context" + "time" + + entsql "entgo.io/ent/dialect/sql" + + "github.com/stackmon/otc-status-dashboard/ent" + "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/internal/event" +) + +// The facade keeps exposing the domain structs from models.go; Ent entities +// never leave this package. These mappers are the only place where both +// representations meet. + +func optTimePtr(v time.Time) *time.Time { + if v.IsZero() { + return nil + } + return &v +} + +func timePtr(v time.Time) *time.Time { + return &v +} + +func intPtr(v int) *int { + return &v +} + +func incidentFromEnt(e *ent.Incident) *Incident { + inc := &Incident{ + ID: uint(e.ID), + Text: &e.Text, + Description: e.Description, + StartDate: timePtr(e.StartDate), + EndDate: optTimePtr(e.EndDate), + Impact: intPtr(e.Impact), + Status: event.Status(e.Status), + System: e.System, + Type: e.Type.String(), + CreatedAt: optTimePtr(e.CreatedAt), + ModifiedAt: optTimePtr(e.ModifiedAt), + DeletedAt: optTimePtr(e.DeletedAt), + CreatedBy: e.CreatedBy, + ContactEmail: e.ContactEmail, + Version: intPtr(e.Version), + } + + if e.Edges.Components != nil { + inc.Components = make([]Component, 0, len(e.Edges.Components)) + for _, c := range e.Edges.Components { + inc.Components = append(inc.Components, componentFromEnt(c)) + } + } + + return inc +} + +func incidentStatusFromEnt(e *ent.IncidentStatus) IncidentStatus { + return IncidentStatus{ + ID: uint(e.ID), + IncidentID: uint(e.IncidentID), + Status: event.Status(e.Status), + Text: e.Text, + Timestamp: e.Timestamp, + CreatedAt: optTimePtr(e.CreatedAt), + ModifiedAt: optTimePtr(e.ModifiedAt), + DeletedAt: optTimePtr(e.DeletedAt), + CreatedBy: e.CreatedBy, + ModifiedBy: e.ModifiedBy, + } +} + +func componentFromEnt(e *ent.Component) Component { + c := Component{ + ID: uint(e.ID), + Name: e.Name, + CreatedAt: optTimePtr(e.CreatedAt), + ModifiedAt: optTimePtr(e.ModifiedAt), + DeletedAt: optTimePtr(e.DeletedAt), + } + + if e.Edges.Attributes != nil { + c.Attrs = make([]ComponentAttr, 0, len(e.Edges.Attributes)) + for _, a := range e.Edges.Attributes { + c.Attrs = append(c.Attrs, componentAttrFromEnt(a)) + } + } + + if e.Edges.Incidents != nil { + c.Incidents = make([]*Incident, 0, len(e.Edges.Incidents)) + for _, i := range e.Edges.Incidents { + c.Incidents = append(c.Incidents, incidentFromEnt(i)) + } + } + + return c +} + +func componentAttrFromEnt(e *ent.ComponentAttr) ComponentAttr { + return ComponentAttr{ + ID: uint(e.ID), + ComponentID: uint(e.ComponentID), + Name: e.Name, + Value: e.Value, + } +} + +// statusesByIncident loads the update history for the given incidents. The Ent +// schema has no status edge (production carries no foreign key on +// incident_status), so callers attach the result themselves. +func (db *DB) statusesByIncident(ctx context.Context, ids []int) (map[int][]IncidentStatus, error) { + grouped := make(map[int][]IncidentStatus, len(ids)) + if len(ids) == 0 { + return grouped, nil + } + + rows, err := db.e.IncidentStatus.Query(). + Where(incidentstatus.IncidentIDIn(ids...)). + Order(incidentstatus.ByID(entsql.OrderAsc())). + All(ctx) + if err != nil { + return nil, err + } + + for _, r := range rows { + grouped[r.IncidentID] = append(grouped[r.IncidentID], incidentStatusFromEnt(r)) + } + + return grouped, nil +} + +func attachStatuses(incidents []*Incident, grouped map[int][]IncidentStatus) { + for _, inc := range incidents { + if s, ok := grouped[int(inc.ID)]; ok { + inc.Statuses = s + continue + } + inc.Statuses = []IncidentStatus{} + } +} + +func incidentIDs(rows []*ent.Incident) []int { + ids := make([]int, 0, len(rows)) + for _, r := range rows { + ids = append(ids, r.ID) + } + return ids +} diff --git a/internal/db/mock.go b/internal/db/mock.go index fffffc2..cbc3bff 100644 --- a/internal/db/mock.go +++ b/internal/db/mock.go @@ -1,9 +1,13 @@ package db import ( + "entgo.io/ent/dialect" + entsql "entgo.io/ent/dialect/sql" "github.com/DATA-DOG/go-sqlmock" "gorm.io/driver/postgres" "gorm.io/gorm" + + "github.com/stackmon/otc-status-dashboard/ent" ) func NewWithMock() (*DB, sqlmock.Sqlmock, error) { @@ -14,5 +18,6 @@ func NewWithMock() (*DB, sqlmock.Sqlmock, error) { }) g, _ := gorm.Open(dialector, &gorm.Config{}) - return &DB{g: g}, mock, nil + e := ent.NewClient(ent.Driver(entsql.OpenDB(dialect.Postgres, mockDB))) + return &DB{g: g, e: e}, mock, nil } diff --git a/tests/main_test.go b/tests/main_test.go index a8f242a..fdebfef 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -12,7 +12,7 @@ import ( "github.com/golang-migrate/migrate/v4" _ "github.com/golang-migrate/migrate/v4/database/postgres" - _ "github.com/golang-migrate/migrate/v4/source/file" + "github.com/golang-migrate/migrate/v4/source/iofs" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/postgres" "github.com/testcontainers/testcontainers-go/wait" @@ -44,6 +44,22 @@ const ( var databaseURL = "postgresql://%s:%s@localhost:%s/%s" func TestMain(m *testing.M) { + // SD_TEST_DSN points the suite at an existing Postgres instead of starting a + // testcontainer. The DSN must be a complete lib/pq URL, including + // sslmode=disable for servers without TLS, and must reference a scratch + // database: the suite truncates and rewrites its tables. + if dsn := os.Getenv("SD_TEST_DSN"); dsn != "" { + databaseURL = dsn + if errMigr := applyMigrations(dsn); errMigr != nil { + log.Printf("failed to apply migrations: %s", errMigr) + os.Exit(1) + } + + code := m.Run() + testIDP.server.Close() + os.Exit(code) + } + ctx := context.Background() container, err := postgres.Run(ctx, pgImage, @@ -96,10 +112,12 @@ func applyMigrations(dbURL string) error { // Get the project root directory migrationsPath := filepath.Join("..", "db", "migrations") - m, err := migrate.New( - fmt.Sprintf("file://%s", migrationsPath), - dbURL, - ) + src, err := iofs.New(os.DirFS(migrationsPath), ".") + if err != nil { + return fmt.Errorf("failed to open migrations source: %w", err) + } + + m, err := migrate.NewWithSourceInstance("iofs", src, dbURL) if err != nil { return fmt.Errorf("failed to create migrate instance: %w", err) } From 04bc8acb8dd95207075bab972544098970646cc8 Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:05:36 +0200 Subject: [PATCH 04/10] Move the remaining GORM queries, transactions and outbox to Ent The facade no longer holds a gorm handle. Transactions run on Ent through a driver that keeps edge writes on the caller's connection, and the outbox lease plus the public-visibility subqueries stay as hand-written SQL. Timestamps are set per call rather than through global hooks, so paths that previously bypassed the ORM hooks keep their behaviour. Verified against a restored production copy: the transaction, filtered-read and outbox scenarios return the same rows, ids and state as before. --- internal/db/db.go | 631 +++++++++++++++++++------------- internal/db/mappers.go | 29 ++ internal/db/mock.go | 14 +- internal/db/models.go | 141 ++----- internal/db/notification.go | 313 ++++++++++------ internal/db/notification_ops.go | 96 +++-- internal/db/raw.go | 82 +++++ internal/db/tx.go | 92 ++++- internal/db/write.go | 162 ++++++++ 9 files changed, 1040 insertions(+), 520 deletions(-) create mode 100644 internal/db/raw.go create mode 100644 internal/db/write.go diff --git a/internal/db/db.go b/internal/db/db.go index 8b25b62..18b5e7d 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -2,23 +2,22 @@ package db import ( "context" + "database/sql" "errors" "fmt" "time" "entgo.io/ent/dialect" entsql "entgo.io/ent/dialect/sql" - "go.uber.org/zap" - "gorm.io/driver/postgres" - "gorm.io/gorm" - "gorm.io/gorm/clause" - "moul.io/zapgorm2" + + _ "github.com/jackc/pgx/v5/stdlib" "github.com/stackmon/otc-status-dashboard/ent" "github.com/stackmon/otc-status-dashboard/ent/component" "github.com/stackmon/otc-status-dashboard/ent/componentattr" "github.com/stackmon/otc-status-dashboard/ent/incident" "github.com/stackmon/otc-status-dashboard/ent/incidentstatus" + "github.com/stackmon/otc-status-dashboard/ent/predicate" "github.com/stackmon/otc-status-dashboard/internal/conf" "github.com/stackmon/otc-status-dashboard/internal/event" ) @@ -33,39 +32,18 @@ const ( dbConnMaxIdleTime = 30 * time.Second ) -// DB is the storage facade. Both ORMs share one connection pool: methods that -// have been migrated run on Ent, the rest still run on GORM. +// DB is the storage facade over the Ent client and its connection pool. type DB struct { - g *gorm.DB - e *ent.Client + sql *sql.DB + e *ent.Client } func New(c *conf.Config) (*DB, error) { - psql := postgres.New(postgres.Config{ - DSN: c.DB, - }) - - gConf := &gorm.Config{ - NowFunc: func() time.Time { - return time.Now().UTC() - }, - } - - if c.LogLevel != conf.DevelopMode { - logger := zapgorm2.New(zap.L()) - gConf.Logger = logger - } - - g, err := gorm.Open(psql, gConf) + sqlDB, err := sql.Open("pgx", c.DB) if err != nil { return nil, err } - sqlDB, err := g.DB() - if err != nil { - return nil, fmt.Errorf("getting underlying sql.DB: %w", err) - } - sqlDB.SetMaxOpenConns(dbMaxOpenConns) sqlDB.SetMaxIdleConns(dbMaxIdleConns) sqlDB.SetConnMaxLifetime(dbConnMaxLifetime) @@ -73,15 +51,11 @@ func New(c *conf.Config) (*DB, error) { e := ent.NewClient(ent.Driver(entsql.OpenDB(dialect.Postgres, sqlDB))) - return &DB{g: g, e: e}, nil + return &DB{sql: sqlDB, e: e}, nil } func (db *DB) Close() error { - sqlDB, err := db.g.DB() - if err != nil { - return err - } - return sqlDB.Close() + return db.sql.Close() } type IncidentsParams struct { @@ -98,22 +72,27 @@ type IncidentsParams struct { Page *int } -func applyEventsFilters(base *gorm.DB, params *IncidentsParams, isAuth bool) (*gorm.DB, error) { +func applyEventsFilters(params *IncidentsParams, isAuth bool) ([]predicate.Incident, error) { + var preds []predicate.Incident + if params.Types != nil { - base = base.Where("incident.type IN (?)", params.Types) + types := make([]incident.Type, 0, len(params.Types)) + for _, t := range params.Types { + types = append(types, incident.Type(t)) + } + preds = append(preds, incident.TypeIn(types...)) } if params.Impact != nil { - base = base.Where("incident.impact = ?", *params.Impact) + preds = append(preds, incident.ImpactEQ(*params.Impact)) } if params.IsSystem != nil { - base = base.Where("incident.system = ?", *params.IsSystem) + preds = append(preds, incident.SystemEQ(*params.IsSystem)) } if len(params.ComponentIDs) > 0 { - base = base.Joins("JOIN incident_component_relation icr ON icr.incident_id = incident.id"). - Where("icr.component_id IN (?)", params.ComponentIDs).Group("incident.id") + preds = append(preds, incident.HasComponentsWith(component.IDIn(params.ComponentIDs...))) } // it's a special case for active events @@ -122,124 +101,139 @@ func applyEventsFilters(base *gorm.DB, params *IncidentsParams, isAuth bool) (*g return nil, ErrDBIncidentFilterActiveFalse //nolint:wrapcheck } currentTime := time.Now().UTC() - base = base.Where("(incident.end_date IS NULL) OR "+ - "(incident.start_date <= ? AND "+ - "incident.end_date >= ? AND "+ - "incident.status NOT IN (?))", - currentTime, - currentTime, - []event.Status{event.IncidentResolved, - event.MaintenanceCompleted, - event.MaintenanceCancelled, - event.MaintenancePendingReview, - event.MaintenanceReviewed, - event.InfoCompleted, - event.InfoCancelled}) + preds = append(preds, incident.Or( + incident.EndDateIsNil(), + incident.And( + incident.StartDateLTE(currentTime), + incident.EndDateGTE(currentTime), + incident.StatusNotIn( + string(event.IncidentResolved), + string(event.MaintenanceCompleted), + string(event.MaintenanceCancelled), + string(event.MaintenancePendingReview), + string(event.MaintenanceReviewed), + string(event.InfoCompleted), + string(event.InfoCancelled), + ), + ), + )) } if params.Status != nil { - base = base.Where("incident.status = ?", params.Status) + preds = append(preds, incident.StatusEQ(string(*params.Status))) } switch { case params.StartDate != nil && params.EndDate != nil: - base = base.Where("incident.start_date >= ? AND incident.end_date <= ?", *params.StartDate, *params.EndDate) + preds = append(preds, + incident.StartDateGTE(*params.StartDate), + incident.EndDateLTE(*params.EndDate)) case params.StartDate != nil && params.EndDate == nil: - base = base.Where("incident.start_date >= ?", *params.StartDate) + preds = append(preds, incident.StartDateGTE(*params.StartDate)) case params.EndDate != nil && params.StartDate == nil: - base = base.Where("incident.end_date <= ?", *params.EndDate) + preds = append(preds, incident.EndDateLTE(*params.EndDate)) } if !isAuth { - base = base.Where( - "NOT (incident.type = ? AND incident.status IN (?, ?))", - event.TypeMaintenance, event.MaintenancePendingReview, event.MaintenanceReviewed, - ) - // Hide cancelled maintenance events that never reached a public status (planned or later). - base = base.Where( - "NOT (incident.type = ? AND incident.status = ? AND "+ - "NOT EXISTS (SELECT 1 FROM incident_status WHERE incident_status.incident_id = incident.id "+ - "AND incident_status.status IN (?, ?, ?, ?)))", - event.TypeMaintenance, event.MaintenanceCancelled, - event.MaintenancePlanned, event.MaintenanceInProgress, event.MaintenanceModified, event.MaintenanceCompleted, - ) + preds = append(preds, publicEventPredicates()...) } - return base, nil + return preds, nil } -func (db *DB) fetchPaginatedEvents(filteredBase *gorm.DB, param *IncidentsParams) ([]*Incident, error) { - var events []*Incident - - subQuery := filteredBase. - Select("incident.id"). - Order("incident.start_date DESC"). - Limit(*param.Limit) - - if param.Page != nil && *param.Page > 1 { - subQuery = subQuery.Offset((*param.Page - 1) * *param.Limit) - } - - r := db.g.Model(&Incident{}). - Joins("JOIN (?) AS filtered_ids ON filtered_ids.id = incident.id", subQuery). - Preload("Statuses"). - Preload("Components", func(db *gorm.DB) *gorm.DB { return db.Select("ID, Name") }). - Preload("Components.Attrs"). - Order("incident.start_date DESC") - - if err := r.Find(&events).Error; err != nil { - return nil, err +// publicEventPredicates hides maintenance awaiting review and cancelled +// maintenance that never reached a public status. +func publicEventPredicates() []predicate.Incident { + return []predicate.Incident{ + incident.Not(incident.And( + incident.TypeEQ(incident.TypeMaintenance), + incident.StatusIn( + string(event.MaintenancePendingReview), + string(event.MaintenanceReviewed), + ), + )), + incident.Not(incident.And( + incident.TypeEQ(incident.TypeMaintenance), + incident.StatusEQ(string(event.MaintenanceCancelled)), + noPublicStatus(), + )), } - return events, nil } -func (db *DB) fetchUnpaginatedEvents(filteredBase *gorm.DB, param *IncidentsParams) ([]*Incident, error) { - var events []*Incident - - r := filteredBase.Order("incident.start_date DESC") - if param.LastCount > 0 { - r = r.Limit(param.LastCount) - } - if err := r.Preload("Statuses"). - Preload("Components", func(db *gorm.DB) *gorm.DB { return db.Select("ID, Name") }). - Preload("Components.Attrs"). - Find(&events).Error; err != nil { - return nil, err +// noPublicStatus matches events without any public maintenance update. Ent has no +// edge to incident_status (production carries no foreign key on it), so the +// correlated subquery stays raw. +func noPublicStatus() predicate.Incident { + return func(s *entsql.Selector) { + s.Where(entsql.P(func(b *entsql.Builder) { + b.WriteString(`NOT EXISTS (SELECT 1 FROM "incident_status" WHERE ` + + `"incident_status"."incident_id" = "incident"."id" AND "incident_status"."status" IN (`) + b.Args( + string(event.MaintenancePlanned), + string(event.MaintenanceInProgress), + string(event.MaintenanceModified), + string(event.MaintenanceCompleted), + ) + b.WriteString("))") + })) } - return events, nil } // GetEventsWithCount retrieves events based on the provided parameters, with pagination and total count. func (db *DB) GetEventsWithCount(isAuth bool, params ...*IncidentsParams) ([]*Incident, int64, error) { var param IncidentsParams - var total int64 - var events []*Incident if len(params) > 0 && params[0] != nil { param = *params[0] } - // Base query for filtering - base := db.g.Model(&Incident{}) + ctx := context.Background() - filteredBase, err := applyEventsFilters(base, ¶m, isAuth) + preds, err := applyEventsFilters(¶m, isAuth) if err != nil { return nil, 0, err } // Get total count before applying limit and offset. - if err = filteredBase.Count(&total).Error; err != nil { + count, err := db.e.Incident.Query().Where(preds...).Count(ctx) + if err != nil { return nil, 0, err } + total := int64(count) - if param.Limit != nil && *param.Limit > 0 { - events, err = db.fetchPaginatedEvents(filteredBase, ¶m) - } else { - events, err = db.fetchUnpaginatedEvents(filteredBase, ¶m) + query := db.e.Incident.Query(). + Where(preds...). + WithComponents(func(q *ent.ComponentQuery) { + q.Select(component.FieldID, component.FieldName) + q.WithAttributes() + }). + Order(incident.ByStartDate(entsql.OrderDesc())) + + switch { + case param.Limit != nil && *param.Limit > 0: + query = query.Limit(*param.Limit) + if param.Page != nil && *param.Page > 1 { + query = query.Offset((*param.Page - 1) * *param.Limit) + } + case param.LastCount > 0: + query = query.Limit(param.LastCount) } + rows, err := query.All(ctx) if err != nil { return nil, 0, err } + + events := make([]*Incident, 0, len(rows)) + for _, row := range rows { + events = append(events, incidentFromEnt(row)) + } + + grouped, err := db.statusesByIncident(ctx, incidentIDs(rows)) + if err != nil { + return nil, 0, err + } + attachStatuses(events, grouped) + return events, total, nil } @@ -285,26 +279,114 @@ func (db *DB) GetIncident(id int) (*Incident, error) { // WithTx runs fn inside a single transaction on the shared connection pool. // Callers use it to write a business change and enqueue its notification atomically. func (db *DB) WithTx(ctx context.Context, fn func(tx *Tx) error) error { - return db.g.WithContext(ctx).Transaction(func(gtx *gorm.DB) error { - return fn(&Tx{g: gtx}) - }) + tx, err := db.begin(ctx) + if err != nil { + return err + } + defer func() { _ = tx.rollback() }() + + if err = fn(tx); err != nil { + return err + } + return tx.commit() } // SaveIncidentTx creates an incident using the provided transaction. func (db *DB) SaveIncidentTx(tx *Tx, inc *Incident) (uint, error) { - if err := tx.g.Create(inc).Error; err != nil { + ctx := context.Background() + c := db.clientFor(tx) + + now := time.Now().UTC() + createdAt := now + if inc.CreatedAt != nil { + createdAt = *inc.CreatedAt + } + modifiedAt := now + if inc.ModifiedAt != nil { + modifiedAt = *inc.ModifiedAt + } + + inc.CreatedAt = &createdAt + inc.ModifiedAt = &modifiedAt + + create := c.Incident.Create(). + SetText(valueOr(inc.Text, "")). + SetStartDate(valueOr(inc.StartDate, now)). + SetImpact(valueOr(inc.Impact, 0)). + SetSystem(inc.System). + SetType(incident.Type(inc.Type)). + SetCreatedAt(createdAt). + SetModifiedAt(modifiedAt) + + if inc.Description != nil { + create.SetDescription(*inc.Description) + } + if inc.EndDate != nil { + create.SetEndDate(*inc.EndDate) + } + if inc.Status != "" { + create.SetStatus(string(inc.Status)) + } + if inc.CreatedBy != nil { + create.SetCreatedBy(*inc.CreatedBy) + } + if inc.ContactEmail != nil { + create.SetContactEmail(*inc.ContactEmail) + } + if inc.Version != nil { + create.SetVersion(*inc.Version) + } + + componentIDs := make([]int, 0, len(inc.Components)) + for i := range inc.Components { + if inc.Components[i].ID != 0 { + componentIDs = append(componentIDs, int(inc.Components[i].ID)) + } + } + if len(componentIDs) > 0 { + create.AddComponentIDs(componentIDs...) + } + + created, err := create.Save(ctx) + if err != nil { return 0, err } + + inc.ID = uint(created.ID) + inc.Version = intPtr(created.Version) + + for i := range inc.Statuses { + if inc.Statuses[i].ID != 0 { + continue + } + id, errStatus := insertIncidentStatus(ctx, c, &inc.Statuses[i], inc.ID) + if errStatus != nil { + return 0, errStatus + } + inc.Statuses[i].ID = uint(id) + inc.Statuses[i].IncidentID = inc.ID + } + return inc.ID, nil } func (db *DB) SaveIncident(inc *Incident) (uint, error) { - return db.SaveIncidentTx(&Tx{g: db.g}, inc) + return db.SaveIncidentTx(nil, inc) } // ModifyIncidentTx applies a modification (with maintenance optimistic locking and // new status inserts) using the provided transaction. func (db *DB) ModifyIncidentTx(tx *Tx, inc *Incident) error { + return db.modifyIncident(context.Background(), db.clientFor(tx), inc) +} + +func (db *DB) ModifyIncident(inc *Incident) error { + return db.execWithTx(context.Background(), nil, func(client *ent.Client, _ entsql.ExecQuerier) error { + return db.modifyIncident(context.Background(), client, inc) + }) +} + +func (db *DB) modifyIncident(ctx context.Context, c *ent.Client, inc *Incident) error { if inc.Version == nil { return errors.New("version is required for event modification") } @@ -313,19 +395,55 @@ func (db *DB) ModifyIncidentTx(tx *Tx, inc *Incident) error { newVersion := expectedVersion + 1 inc.Version = &newVersion - query := tx.g.Model(&Incident{}).Where("id = ?", inc.ID) + now := time.Now().UTC() + // A struct-based update writes the non-zero fields only, so nil pointers and + // empty scalars are left untouched, mirroring the previous ORM behaviour. + update := c.Incident.Update().Where(incident.IDEQ(int(inc.ID))) if inc.Type == event.TypeMaintenance { - query = query.Where("version = ?", expectedVersion) + update.Where(incident.VersionEQ(expectedVersion)) } - r := query.Omit("Statuses", "Components").Updates(inc) - - if r.Error != nil { - return r.Error + if inc.Text != nil { + update.SetText(*inc.Text) } + if inc.Description != nil { + update.SetDescription(*inc.Description) + } + if inc.StartDate != nil { + update.SetStartDate(*inc.StartDate) + } + if inc.EndDate != nil { + update.SetEndDate(*inc.EndDate) + } + if inc.Impact != nil { + update.SetImpact(*inc.Impact) + } + if inc.Status != "" { + update.SetStatus(string(inc.Status)) + } + if inc.System { + update.SetSystem(true) + } + if inc.Type != "" { + update.SetType(incident.Type(inc.Type)) + } + if inc.CreatedAt != nil { + update.SetCreatedAt(*inc.CreatedAt) + } + if inc.CreatedBy != nil { + update.SetCreatedBy(*inc.CreatedBy) + } + if inc.ContactEmail != nil { + update.SetContactEmail(*inc.ContactEmail) + } + update.SetVersion(newVersion).SetModifiedAt(now) - if inc.Type == event.TypeMaintenance && r.RowsAffected == 0 { + affected, err := update.Save(ctx) + if err != nil { + return err + } + if inc.Type == event.TypeMaintenance && affected == 0 { return ErrVersionConflict } @@ -333,23 +451,17 @@ func (db *DB) ModifyIncidentTx(tx *Tx, inc *Incident) error { if inc.Statuses[i].ID != 0 { continue } - if inc.Statuses[i].IncidentID == 0 { - inc.Statuses[i].IncidentID = inc.ID - } - if err := tx.g.Create(&inc.Statuses[i]).Error; err != nil { - return err + id, errStatus := insertIncidentStatus(ctx, c, &inc.Statuses[i], inc.ID) + if errStatus != nil { + return errStatus } + inc.Statuses[i].ID = uint(id) + inc.Statuses[i].IncidentID = inc.ID } return nil } -func (db *DB) ModifyIncident(inc *Incident) error { - return db.g.Transaction(func(gtx *gorm.DB) error { - return db.ModifyIncidentTx(&Tx{g: gtx}, inc) - }) -} - // AddComponentToIncident adds a component and a status update to an incident using optimistic locking. func (db *DB) AddComponentToIncident(inc *Incident, comp *Component, status IncidentStatus) error { if inc.Version == nil { @@ -358,34 +470,30 @@ func (db *DB) AddComponentToIncident(inc *Incident, comp *Component, status Inci expectedVersion := *inc.Version newVersion := expectedVersion + 1 + ctx := context.Background() - err := db.g.Transaction(func(tx *gorm.DB) error { - // Update version with optimistic lock - r := tx.Model(&Incident{}). - Where("id = ? AND version = ?", inc.ID, expectedVersion). - Updates(map[string]interface{}{ - "version": newVersion, - }) - if r.Error != nil { - return r.Error + err := db.execWithTx(ctx, nil, func(client *ent.Client, _ entsql.ExecQuerier) error { + affected, err := client.Incident.Update(). + Where(incident.IDEQ(int(inc.ID)), incident.VersionEQ(expectedVersion)). + SetVersion(newVersion). + Save(ctx) + if err != nil { + return err } - if r.RowsAffected == 0 { + if affected == 0 { return ErrVersionConflict } - // Add component to incident via association - if err := tx.Model(inc).Association("Components").Append(comp); err != nil { - return err + if comp.ID != 0 { + if _, err = client.Incident.UpdateOneID(int(inc.ID)).AddComponentIDs(int(comp.ID)).Save(ctx); err != nil { + return err + } + inc.Components = append(inc.Components, *comp) } - // Create status update - if status.IncidentID == 0 { - status.IncidentID = inc.ID - } - if err := tx.Create(&status).Error; err != nil { + if _, err = insertIncidentStatus(ctx, client, &status, inc.ID); err != nil { return err } - return nil }) if err != nil { @@ -413,95 +521,108 @@ func (db *DB) ReOpenIncident(inc *Incident) error { // exceptions for "event.TypeMaintenance, event.MaintenancePendingReview, event.MaintenanceReviewed". // Supports optional filtering parameters: isActive, Types, LastCount. func (db *DB) GetEventsByComponentID(componentID uint, params ...*IncidentsParams) ([]*Incident, error) { - // Get all incidents for this component - var incidents []*Incident var param IncidentsParams if params != nil && params[0] != nil { param = *params[0] } - r := db.g.Model(&Incident{}). - Joins("JOIN incident_component_relation icr ON icr.incident_id = incident.id"). - Where("icr.component_id = ?", componentID). - Where("NOT (incident.type = ? AND incident.status IN (?, ?))", - event.TypeMaintenance, event.MaintenancePendingReview, event.MaintenanceReviewed). - Where("NOT (incident.type = ? AND incident.status = ? AND "+ - "NOT EXISTS (SELECT 1 FROM incident_status WHERE incident_status.incident_id = incident.id "+ - "AND incident_status.status IN (?, ?, ?, ?)))", - event.TypeMaintenance, event.MaintenanceCancelled, - event.MaintenancePlanned, event.MaintenanceInProgress, event.MaintenanceModified, event.MaintenanceCompleted). - Preload("Statuses"). - Preload("Components", func(db *gorm.DB) *gorm.DB { - return db.Select("ID, Name") - }). - Preload("Components.Attrs") + ctx := context.Background() - if param.LastCount != 0 { - r.Order("incident.id desc").Limit(param.LastCount) + preds := []predicate.Incident{ + incident.HasComponentsWith(component.IDEQ(int(componentID))), } + preds = append(preds, publicEventPredicates()...) if param.IsActive != nil && *param.IsActive { currentTime := time.Now().UTC() - r.Where("(incident.end_date IS NULL) OR "+ - "(incident.start_date <= ? AND "+ - "incident.end_date >= ? AND "+ - "incident.status NOT IN (?))", - currentTime, - currentTime, - []event.Status{event.IncidentResolved, - event.MaintenanceCompleted, - event.MaintenanceCancelled, - event.InfoCompleted, - event.InfoCancelled}) + preds = append(preds, incident.Or( + incident.EndDateIsNil(), + incident.And( + incident.StartDateLTE(currentTime), + incident.EndDateGTE(currentTime), + incident.StatusNotIn( + string(event.IncidentResolved), + string(event.MaintenanceCompleted), + string(event.MaintenanceCancelled), + string(event.InfoCompleted), + string(event.InfoCancelled), + ), + ), + )) } if len(param.Types) > 0 { - r.Where("incident.type IN (?)", param.Types) + types := make([]incident.Type, 0, len(param.Types)) + for _, t := range param.Types { + types = append(types, incident.Type(t)) + } + preds = append(preds, incident.TypeIn(types...)) + } + + query := db.e.Incident.Query(). + Where(preds...). + WithComponents(func(q *ent.ComponentQuery) { + q.Select(component.FieldID, component.FieldName) + q.WithAttributes() + }) + + if param.LastCount != 0 { + query = query.Order(incident.ByID(entsql.OrderDesc())).Limit(param.LastCount) + } else { + query = query.Order(incident.ByID(entsql.OrderAsc())) } - r.Find(&incidents) - if r.Error != nil { - return nil, r.Error + rows, err := query.All(ctx) + if err != nil { + return nil, err + } + + incidents := make([]*Incident, 0, len(rows)) + for _, row := range rows { + incidents = append(incidents, incidentFromEnt(row)) + } + + grouped, err := db.statusesByIncident(ctx, incidentIDs(rows)) + if err != nil { + return nil, err } + attachStatuses(incidents, grouped) + return incidents, nil } func (db *DB) GetIncidentsByComponentAttr(attr *ComponentAttr, params ...*IncidentsParams) ([]*Incident, error) { // Get all public incidents for components with this attribute. // Maintenance events in pending_review/reviewed status are excluded (require authentication). - var incidents []*Incident var param IncidentsParams if params != nil && params[0] != nil { param = *params[0] } - r := db.g.Model(&Incident{}). - Joins("JOIN incident_component_relation icr ON icr.incident_id = incident.id"). - Joins("JOIN component_attribute ca ON ca.component_id = icr.component_id"). - Where("ca.name = ? AND ca.value = ?", attr.Name, attr.Value). - Where("NOT (incident.type = ? AND incident.status IN (?, ?))", - event.TypeMaintenance, event.MaintenancePendingReview, event.MaintenanceReviewed). - Where("NOT (incident.type = ? AND incident.status = ? AND "+ - "NOT EXISTS (SELECT 1 FROM incident_status WHERE incident_status.incident_id = incident.id "+ - "AND incident_status.status IN (?, ?, ?, ?)))", - event.TypeMaintenance, event.MaintenanceCancelled, - event.MaintenancePlanned, event.MaintenanceInProgress, event.MaintenanceModified, event.MaintenanceCompleted). - Preload("Statuses"). - Preload("Components", func(db *gorm.DB) *gorm.DB { - return db.Select("ID, Name") - }). - Preload("Components.Attrs") + ctx := context.Background() + // The previous ORM joined the relation and the attribute tables directly, so an + // incident matched by several components appeared once per match. The raw id + // query keeps that shape and its ordering. + query := incidentsByComponentAttrQuery + args := []any{ + attr.Name, attr.Value, + string(event.TypeMaintenance), string(event.MaintenancePendingReview), string(event.MaintenanceReviewed), + string(event.TypeMaintenance), string(event.MaintenanceCancelled), + string(event.MaintenancePlanned), string(event.MaintenanceInProgress), + string(event.MaintenanceModified), string(event.MaintenanceCompleted), + } if param.LastCount != 0 { - r.Order("incident.id desc").Limit(param.LastCount) + query += " ORDER BY incident.id DESC LIMIT $12" + args = append(args, param.LastCount) } - r.Find(&incidents) - if r.Error != nil { - return nil, r.Error + ids, err := scanIntColumn(ctx, db.rawFor(nil), query, args...) + if err != nil { + return nil, err } - return incidents, nil + return db.incidentsByIDs(ctx, ids) } func (db *DB) GetOpenedIncidentsWithComponent(_ string, _ []ComponentAttr) (*Incident, error) { @@ -752,23 +873,19 @@ func (db *DB) MoveComponentFromOldToAnotherIncident( incOld.EndDate = &timeNow } - err := db.g.Transaction(func(tx *gorm.DB) error { - if !closeOld { - if err := tx.Model(incOld).Association("Components").Delete(comp); err != nil { - return err + err := db.execWithTx(context.Background(), nil, func(client *ent.Client, _ entsql.ExecQuerier) error { + if !closeOld && comp.ID != 0 { + if errRemove := removeIncidentComponent(context.Background(), client, incOld.ID, comp.ID); errRemove != nil { + return errRemove } + dropIncidentComponent(incOld, comp.ID) } - if r := tx.Save(incNew); r.Error != nil { - return r.Error - } - if r := tx.Save(incOld); r.Error != nil { - return r.Error + if errSave := saveIncidentFull(context.Background(), client, incNew); errSave != nil { + return errSave } - - return nil + return saveIncidentFull(context.Background(), client, incOld) }) - if err != nil { return nil, err } @@ -824,25 +941,23 @@ func (db *DB) ExtractComponentsToNewIncident( } // Use a transaction to save both incidents with their statuses and update associations - err = db.g.Transaction(func(tx *gorm.DB) error { + err = db.execWithTx(context.Background(), nil, func(client *ent.Client, _ entsql.ExecQuerier) error { // Remove component from old incident - for _, c := range comp { - if errDel := tx.Model(incOld).Association("Components").Delete(c); err != nil { - return errDel + for i := range comp { + if comp[i].ID == 0 { + continue } + if errRemove := removeIncidentComponent(context.Background(), client, incOld.ID, comp[i].ID); errRemove != nil { + return errRemove + } + dropIncidentComponent(incOld, comp[i].ID) } - // Save both incidents with their new statuses (Save() saves associated records) - if r := tx.Save(inc); r.Error != nil { - return r.Error - } - if r := tx.Save(incOld); r.Error != nil { - return r.Error + if errSave := saveIncidentFull(context.Background(), client, inc); errSave != nil { + return errSave } - - return nil + return saveIncidentFull(context.Background(), client, incOld) }) - if err != nil { return nil, err } @@ -976,27 +1091,35 @@ func (db *DB) GetEventUpdates(incidentID uint) ([]IncidentStatus, error) { // ModifyEventUpdateTx patches an event status update's text using the provided // transaction and returns the updated row. func (db *DB) ModifyEventUpdateTx(tx *Tx, update IncidentStatus) (IncidentStatus, error) { + ctx := context.Background() + c := db.clientFor(tx) now := time.Now().UTC() - var updated IncidentStatus - r := tx.g.Model(&IncidentStatus{}). - Clauses(clause.Returning{}). - Where("id = ? AND incident_id = ?", update.ID, update.IncidentID). - Updates(map[string]interface{}{ - "text": update.Text, - "modified_at": now, - }). - Scan(&updated) - if r.Error != nil { - return IncidentStatus{}, r.Error + affected, err := c.IncidentStatus.Update(). + Where( + incidentstatus.IDEQ(int(update.ID)), + incidentstatus.IncidentIDEQ(int(update.IncidentID)), + ). + SetText(update.Text). + SetModifiedAt(now). + Save(ctx) + if err != nil { + return IncidentStatus{}, err } - if r.RowsAffected == 0 { + if affected == 0 { return IncidentStatus{}, ErrDBEventUpdateDSNotExist } - return updated, nil + row, err := c.IncidentStatus.Query(). + Where(incidentstatus.IDEQ(int(update.ID))). + Only(ctx) + if err != nil { + return IncidentStatus{}, err + } + + return incidentStatusFromEnt(row), nil } func (db *DB) ModifyEventUpdate(update IncidentStatus) (IncidentStatus, error) { - return db.ModifyEventUpdateTx(&Tx{g: db.g}, update) + return db.ModifyEventUpdateTx(nil, update) } diff --git a/internal/db/mappers.go b/internal/db/mappers.go index 7b2d318..ebbe78d 100644 --- a/internal/db/mappers.go +++ b/internal/db/mappers.go @@ -143,6 +143,35 @@ func attachStatuses(incidents []*Incident, grouped map[int][]IncidentStatus) { } } +func notificationOutboxFromEnt(e *ent.NotificationOutbox) NotificationOutbox { + row := NotificationOutbox{ + ID: uint(e.ID), + Kind: e.Kind, + IncidentID: uint(e.IncidentID), + Recipient: e.Recipient, + Payload: e.Payload, + ChangeID: e.ChangeID, + DedupKey: e.DedupKey, + Status: e.Status, + Attempts: e.Attempts, + CreatedAt: e.CreatedAt, + UpdatedAt: e.UpdatedAt, + } + if !e.NextAttemptAt.IsZero() { + row.NextAttemptAt = &e.NextAttemptAt + } + if e.LockedBy != "" { + row.LockedBy = &e.LockedBy + } + if !e.LockedAt.IsZero() { + row.LockedAt = &e.LockedAt + } + if e.LastError != "" { + row.LastError = &e.LastError + } + return row +} + func incidentIDs(rows []*ent.Incident) []int { ids := make([]int, 0, len(rows)) for _, r := range rows { diff --git a/internal/db/mock.go b/internal/db/mock.go index cbc3bff..32c8cba 100644 --- a/internal/db/mock.go +++ b/internal/db/mock.go @@ -4,20 +4,16 @@ import ( "entgo.io/ent/dialect" entsql "entgo.io/ent/dialect/sql" "github.com/DATA-DOG/go-sqlmock" - "gorm.io/driver/postgres" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/ent" ) func NewWithMock() (*DB, sqlmock.Sqlmock, error) { - mockDB, mock, _ := sqlmock.New() - dialector := postgres.New(postgres.Config{ - Conn: mockDB, - DriverName: "postgres", - }) + mockDB, mock, err := sqlmock.New() + if err != nil { + return nil, nil, err + } - g, _ := gorm.Open(dialector, &gorm.Config{}) e := ent.NewClient(ent.Driver(entsql.OpenDB(dialect.Postgres, mockDB))) - return &DB{g: g, e: e}, mock, nil + return &DB{sql: mockDB, e: e}, mock, nil } diff --git a/internal/db/models.go b/internal/db/models.go index e557a5b..a1a4f6d 100644 --- a/internal/db/models.go +++ b/internal/db/models.go @@ -4,8 +4,6 @@ import ( "fmt" "time" - "gorm.io/gorm" - "github.com/stackmon/otc-status-dashboard/internal/event" ) @@ -13,35 +11,12 @@ type Component struct { ID uint `json:"id"` Name string `json:"name,omitempty"` Attrs []ComponentAttr `json:"attributes,omitempty"` - Incidents []*Incident `json:"incidents,omitempty" gorm:"many2many:incident_component_relation"` + Incidents []*Incident `json:"incidents,omitempty"` CreatedAt *time.Time `json:"-"` ModifiedAt *time.Time `json:"-"` DeletedAt *time.Time `json:"-"` } -func (c *Component) TableName() string { - return "component" -} - -// BeforeCreate GORM hook to set created_at and modified_at. -func (c *Component) BeforeCreate(_ *gorm.DB) error { - now := time.Now().UTC() - if c.CreatedAt == nil { - c.CreatedAt = &now - } - if c.ModifiedAt == nil { - c.ModifiedAt = &now - } - return nil -} - -// BeforeUpdate GORM hook to set modified_at. -func (c *Component) BeforeUpdate(_ *gorm.DB) error { - now := time.Now().UTC() - c.ModifiedAt = &now - return nil -} - func (c *Component) PrintAttrs() string { var category, region, compType string for _, a := range c.Attrs { @@ -88,61 +63,34 @@ type ComponentAttr struct { Value string `json:"value"` } -func (c *ComponentAttr) TableName() string { - return "component_attribute" -} - // Incident is a db table representation. type Incident struct { ID uint `json:"id"` - Text *string `json:"text" gorm:"not null"` - Description *string `json:"description" gorm:"type:varchar(1500)"` - StartDate *time.Time `json:"start_date" gorm:"not null"` + Text *string `json:"text"` + Description *string `json:"description"` + StartDate *time.Time `json:"start_date"` EndDate *time.Time `json:"end_date"` - Impact *int `json:"impact" gorm:"not null"` - Statuses []IncidentStatus `json:"updates" gorm:"foreignKey:IncidentID"` - Status event.Status `json:"status" gorm:"type:varchar(50)"` - System bool `json:"system" gorm:"not null"` - Type string `json:"type" gorm:"not null"` - Components []Component `json:"components" gorm:"many2many:incident_component_relation"` + Impact *int `json:"impact"` + Statuses []IncidentStatus `json:"updates"` + Status event.Status `json:"status"` + System bool `json:"system"` + Type string `json:"type"` + Components []Component `json:"components"` CreatedAt *time.Time `json:"created_at,omitempty"` ModifiedAt *time.Time `json:"modified_at,omitempty"` DeletedAt *time.Time `json:"deleted_at,omitempty"` - CreatedBy *string `json:"created_by,omitempty" gorm:"type:varchar(255)"` - ContactEmail *string `json:"contact_email,omitempty" gorm:"type:varchar(255)"` - Version *int `json:"version,omitempty" gorm:"not null;default:1"` -} - -func (in *Incident) TableName() string { - return "incident" + CreatedBy *string `json:"created_by,omitempty"` + ContactEmail *string `json:"contact_email,omitempty"` + Version *int `json:"version,omitempty"` } func (in *Incident) Link() string { return fmt.Sprintf("%s", in.ID, *in.Text) } -// BeforeSave GORM hook to set created_at and modified_at. -func (in *Incident) BeforeSave(_ *gorm.DB) error { - now := time.Now().UTC() - if in.CreatedAt == nil { - in.CreatedAt = &now - } - if in.ModifiedAt == nil { - in.ModifiedAt = &now - } - return nil -} - -// BeforeUpdate GORM hook to set modified_at. -func (in *Incident) BeforeUpdate(_ *gorm.DB) error { - now := time.Now().UTC() - in.ModifiedAt = &now - return nil -} - // IncidentStatus is a db table representation. type IncidentStatus struct { - ID uint `json:"-" gorm:"primaryKey;autoIncrement:true;"` + ID uint `json:"-"` IncidentID uint `json:"-"` Status event.Status `json:"status"` Text string `json:"text"` @@ -150,52 +98,25 @@ type IncidentStatus struct { CreatedAt *time.Time `json:"created_at,omitempty"` ModifiedAt *time.Time `json:"modified_at,omitempty"` DeletedAt *time.Time `json:"deleted_at,omitempty"` - CreatedBy *string `json:"created_by,omitempty" gorm:"type:varchar(255)"` - ModifiedBy *string `json:"modified_by,omitempty" gorm:"type:varchar(255)"` -} - -func (is *IncidentStatus) TableName() string { - return "incident_status" -} - -// BeforeSave GORM hook to set created_at and modified_at. -func (is *IncidentStatus) BeforeSave(_ *gorm.DB) error { - now := time.Now().UTC() - if is.CreatedAt == nil { - is.CreatedAt = &now - } - if is.ModifiedAt == nil { - is.ModifiedAt = &now - } - return nil -} - -// BeforeUpdate GORM hook to set modified_at. -func (is *IncidentStatus) BeforeUpdate(_ *gorm.DB) error { - now := time.Now().UTC() - is.ModifiedAt = &now - return nil + CreatedBy *string `json:"created_by,omitempty"` + ModifiedBy *string `json:"modified_by,omitempty"` } // NotificationOutbox stores one email task per recipient. type NotificationOutbox struct { - ID uint `json:"id" gorm:"primaryKey;autoIncrement:true"` - Kind string `json:"kind" gorm:"type:varchar(64);not null"` - IncidentID uint `json:"incident_id" gorm:"not null"` - Recipient string `json:"recipient" gorm:"type:varchar(255);not null"` - Payload map[string]any `json:"payload" gorm:"type:jsonb;not null;serializer:json"` - ChangeID string `json:"change_id" gorm:"type:uuid;not null"` - DedupKey string `json:"dedup_key" gorm:"column:dedup_key;type:varchar(255);not null;uniqueIndex"` - Status string `json:"status" gorm:"type:varchar(20);not null;default:pending"` - Attempts int `json:"attempts" gorm:"not null;default:0"` - NextAttemptAt *time.Time `json:"next_attempt_at" gorm:"type:timestamptz"` - LockedBy *string `json:"locked_by" gorm:"type:varchar(255)"` - LockedAt *time.Time `json:"locked_at" gorm:"type:timestamptz"` - LastError *string `json:"last_error" gorm:"type:text"` - CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` - UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` -} - -func (no *NotificationOutbox) TableName() string { - return "notification_outbox" + ID uint `json:"id"` + Kind string `json:"kind"` + IncidentID uint `json:"incident_id"` + Recipient string `json:"recipient"` + Payload map[string]any `json:"payload"` + ChangeID string `json:"change_id"` + DedupKey string `json:"dedup_key"` + Status string `json:"status"` + Attempts int `json:"attempts"` + NextAttemptAt *time.Time `json:"next_attempt_at"` + LockedBy *string `json:"locked_by"` + LockedAt *time.Time `json:"locked_at"` + LastError *string `json:"last_error"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } diff --git a/internal/db/notification.go b/internal/db/notification.go index 6f53fa6..4440ae6 100644 --- a/internal/db/notification.go +++ b/internal/db/notification.go @@ -2,11 +2,15 @@ package db import ( "context" + "database/sql" + "encoding/json" "errors" "time" - "gorm.io/gorm" - "gorm.io/gorm/clause" + entsql "entgo.io/ent/dialect/sql" + + "github.com/stackmon/otc-status-dashboard/ent" + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" ) const ( @@ -25,21 +29,15 @@ var ( ErrNotificationNotFound = errors.New("notification: not found") ) -// rowExists checks whether a row with the same dedup key already exists. -func (db *DB) rowExists(tx *gorm.DB, dedupKey string) (bool, error) { - q := db.g - if tx != nil { - q = tx - } +// outboxColumns lists every outbox column in the order selectOutboxRows expects. +const outboxColumns = `id, kind, incident_id, recipient, payload, change_id, dedup_key, status, ` + + `attempts, next_attempt_at, locked_by, locked_at, last_error, created_at, updated_at` - var row NotificationOutbox - if err := q.Select("id").Where("dedup_key = ?", dedupKey).First(&row).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return false, nil - } - return false, err - } - return true, nil +// rowExists checks whether a row with the same dedup key already exists. +func (db *DB) rowExists(ctx context.Context, c *ent.Client, dedupKey string) (bool, error) { + return c.NotificationOutbox.Query(). + Where(notificationoutbox.DedupKeyEQ(dedupKey)). + Exist(ctx) } // Enqueue inserts one outbox row for a single recipient. @@ -49,15 +47,49 @@ func (db *DB) Enqueue(ctx context.Context, tx *Tx, row NotificationOutbox) error return errors.New("notification: dedup_key is required") } - return db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { - exists, err := db.rowExists(gtx, row.DedupKey) + return db.execWithTx(ctx, tx, func(c *ent.Client, _ entsql.ExecQuerier) error { + exists, err := db.rowExists(ctx, c, row.DedupKey) if err != nil { return err } if exists { return ErrNotificationDuplicate } - return gtx.Create(&row).Error + + create := c.NotificationOutbox.Create(). + SetKind(row.Kind). + SetIncidentID(int(row.IncidentID)). + SetRecipient(row.Recipient). + SetPayload(row.Payload). + SetChangeID(row.ChangeID). + SetDedupKey(row.DedupKey) + if row.Status != "" { + create.SetStatus(row.Status) + } + if row.Attempts != 0 { + create.SetAttempts(row.Attempts) + } + if row.NextAttemptAt != nil { + create.SetNextAttemptAt(*row.NextAttemptAt) + } + if row.LockedBy != nil { + create.SetLockedBy(*row.LockedBy) + } + if row.LockedAt != nil { + create.SetLockedAt(*row.LockedAt) + } + if row.LastError != nil { + create.SetLastError(*row.LastError) + } + if !row.CreatedAt.IsZero() { + create.SetCreatedAt(row.CreatedAt) + } + if !row.UpdatedAt.IsZero() { + create.SetUpdatedAt(row.UpdatedAt) + } + + _, err = create.Save(ctx) + return err }) } @@ -69,48 +101,54 @@ func (db *DB) ClaimPending( ) ([]NotificationOutbox, error) { var rows []NotificationOutbox - return rows, db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { - if err := gtx.Clauses(clause.Locking{Strength: "UPDATE", Options: "SKIP LOCKED"}). - Where("status = ?", NotificationStatusPending). - Where("next_attempt_at IS NULL OR next_attempt_at <= ?", time.Now().UTC()). - Order("id ASC"). - Limit(limit). - Find(&rows).Error; err != nil { + err := db.execWithTx(ctx, tx, func(_ *ent.Client, raw entsql.ExecQuerier) error { + claimed, err := selectOutboxRows(ctx, raw, + `SELECT `+outboxColumns+` FROM notification_outbox + WHERE status = $1 AND (next_attempt_at IS NULL OR next_attempt_at <= $2) + ORDER BY id ASC LIMIT $3 FOR UPDATE SKIP LOCKED`, + NotificationStatusPending, time.Now().UTC(), limit) + if err != nil { return err } + now := time.Now().UTC() - for i := range rows { - rows[i].Status = NotificationStatusProcessing - rows[i].Attempts++ - rows[i].LockedBy = &leaseOwner - rows[i].LockedAt = &now - if err := gtx.Model(&rows[i]).Updates(map[string]any{ - "status": rows[i].Status, - "attempts": rows[i].Attempts, - "locked_by": rows[i].LockedBy, - "locked_at": rows[i].LockedAt, - }).Error; err != nil { + for i := range claimed { + claimed[i].Status = NotificationStatusProcessing + claimed[i].Attempts++ + claimed[i].LockedBy = &leaseOwner + claimed[i].LockedAt = &now + + if _, err = raw.ExecContext(ctx, + `UPDATE notification_outbox + SET status = $1, attempts = $2, locked_by = $3, locked_at = $4, updated_at = $5 + WHERE id = $6`, + claimed[i].Status, claimed[i].Attempts, claimed[i].LockedBy, claimed[i].LockedAt, + now, claimed[i].ID); err != nil { return err } } + + rows = claimed return nil }) + return rows, err } // MarkSent marks a row as sent and clears the active lease. func (db *DB) MarkSent(ctx context.Context, tx *Tx, id uint) error { - return db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { - res := gtx.Model(&NotificationOutbox{}). - Where("id = ?", id).Updates(map[string]any{ - "status": NotificationStatusSent, - "locked_by": nil, - "locked_at": nil, - "last_error": nil, - }) - if res.Error != nil { - return res.Error - } - if res.RowsAffected == 0 { + return db.execWithTx(ctx, tx, func(c *ent.Client, _ entsql.ExecQuerier) error { + affected, err := c.NotificationOutbox.Update(). + Where(notificationoutbox.IDEQ(int(id))). + SetStatus(NotificationStatusSent). + ClearLockedBy(). + ClearLockedAt(). + ClearLastError(). + SetUpdatedAt(time.Now().UTC()). + Save(ctx) + if err != nil { + return err + } + if affected == 0 { return ErrNotificationNotFound } return nil @@ -118,20 +156,19 @@ func (db *DB) MarkSent(ctx context.Context, tx *Tx, id uint) error { } // getRowByID loads a single notification row by primary key. -func (db *DB) getRowByID(tx *gorm.DB, id uint) (*NotificationOutbox, error) { - q := db.g - if tx != nil { - q = tx - } - - var row NotificationOutbox - if err := q.First(&row, id).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { +func (db *DB) getRowByID(ctx context.Context, c *ent.Client, id uint) (*NotificationOutbox, error) { + row, err := c.NotificationOutbox.Query(). + Where(notificationoutbox.IDEQ(int(id))). + Only(ctx) + if err != nil { + if ent.IsNotFound(err) { return nil, ErrNotificationNotFound } return nil, err } - return &row, nil + + domain := notificationOutboxFromEnt(row) + return &domain, nil } // MarkFailed marks a row as failed or pending with retry metadata. @@ -140,46 +177,47 @@ func (db *DB) getRowByID(tx *gorm.DB, id uint) (*NotificationOutbox, error) { func (db *DB) MarkFailed( ctx context.Context, tx *Tx, id uint, errText string, maxAttempts int, backoff func(attempts int) time.Time, ) error { - return db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { - row, err := db.getRowByID(gtx, id) + return db.execWithTx(ctx, tx, func(c *ent.Client, _ entsql.ExecQuerier) error { + row, err := db.getRowByID(ctx, c, id) if err != nil { return err } - updates := map[string]any{ - "last_error": errText, - "locked_by": nil, - "locked_at": nil, - } + update := c.NotificationOutbox.Update(). + Where(notificationoutbox.IDEQ(int(id))). + SetLastError(errText). + ClearLockedBy(). + ClearLockedAt(). + SetUpdatedAt(time.Now().UTC()) if row.Attempts >= maxAttempts { - updates["status"] = NotificationStatusFailed - updates["next_attempt_at"] = nil + update.SetStatus(NotificationStatusFailed).ClearNextAttemptAt() } else { - updates["status"] = NotificationStatusPending - updates["next_attempt_at"] = backoff(row.Attempts) + update.SetStatus(NotificationStatusPending).SetNextAttemptAt(backoff(row.Attempts)) } - return gtx.Model(&NotificationOutbox{}).Where("id = ?", id).Updates(updates).Error + _, err = update.Save(ctx) + return err }) } // MarkFailedTerminal fails a row outright, ignoring the remaining attempts. Used for // rejections the server will repeat on every retry, such as an unknown recipient. func (db *DB) MarkFailedTerminal(ctx context.Context, tx *Tx, id uint, errText string) error { - return db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { - res := gtx.Model(&NotificationOutbox{}). - Where("id = ?", id).Updates(map[string]any{ - "status": NotificationStatusFailed, - "last_error": errText, - "next_attempt_at": nil, - "locked_by": nil, - "locked_at": nil, - }) - if res.Error != nil { - return res.Error - } - if res.RowsAffected == 0 { + return db.execWithTx(ctx, tx, func(c *ent.Client, _ entsql.ExecQuerier) error { + affected, err := c.NotificationOutbox.Update(). + Where(notificationoutbox.IDEQ(int(id))). + SetStatus(NotificationStatusFailed). + SetLastError(errText). + ClearNextAttemptAt(). + ClearLockedBy(). + ClearLockedAt(). + SetUpdatedAt(time.Now().UTC()). + Save(ctx) + if err != nil { + return err + } + if affected == 0 { return ErrNotificationNotFound } return nil @@ -193,49 +231,96 @@ func (db *DB) RecoverStaleProcessing( ) ([]NotificationOutbox, error) { var rows []NotificationOutbox - return rows, db.execWithTx(ctx, tx, func(gtx *gorm.DB) error { + err := db.execWithTx(ctx, tx, func(_ *ent.Client, raw entsql.ExecQuerier) error { cutoff := time.Now().UTC().Add(-leaseTimeout) now := time.Now().UTC() - if err := gtx.Clauses(clause.Locking{Strength: "UPDATE", Options: "SKIP LOCKED"}). - Where("status = ?", NotificationStatusProcessing). - Where("locked_at < ?", cutoff). - Find(&rows).Error; err != nil { + + stale, err := selectOutboxRows(ctx, raw, + `SELECT `+outboxColumns+` FROM notification_outbox + WHERE status = $1 AND locked_at < $2 + FOR UPDATE SKIP LOCKED`, + NotificationStatusProcessing, cutoff) + if err != nil { return err } - for i := range rows { - if rows[i].Attempts >= maxAttempts { - rows[i].Status = NotificationStatusFailed - rows[i].NextAttemptAt = nil + + for i := range stale { + if stale[i].Attempts >= maxAttempts { + stale[i].Status = NotificationStatusFailed + stale[i].NextAttemptAt = nil } else { - rows[i].Status = NotificationStatusPending - rows[i].NextAttemptAt = &now + stale[i].Status = NotificationStatusPending + stale[i].NextAttemptAt = &now } - rows[i].LockedBy = nil - rows[i].LockedAt = nil - - if err := gtx.Model(&rows[i]). - Where("status = ?", NotificationStatusProcessing). - Where("locked_at < ?", cutoff). - Updates(map[string]any{ - "status": rows[i].Status, - "next_attempt_at": rows[i].NextAttemptAt, - "locked_by": rows[i].LockedBy, - "locked_at": rows[i].LockedAt, - }).Error; err != nil { + stale[i].LockedBy = nil + stale[i].LockedAt = nil + + if _, err = raw.ExecContext(ctx, + `UPDATE notification_outbox + SET status = $1, next_attempt_at = $2, locked_by = $3, locked_at = $4, updated_at = $5 + WHERE id = $6 AND status = $7 AND locked_at < $8`, + stale[i].Status, stale[i].NextAttemptAt, stale[i].LockedBy, stale[i].LockedAt, + now, stale[i].ID, NotificationStatusProcessing, cutoff); err != nil { return err } } + + rows = stale return nil }) + return rows, err } -// execWithTx runs the callback in a transaction if tx is nil; otherwise it uses the provided tx. -func (db *DB) execWithTx(ctx context.Context, tx *Tx, fn func(*gorm.DB) error) error { - if tx != nil { - return fn(tx.g) +// selectOutboxRows runs a hand-written statement and scans full outbox rows. The +// claim and recovery paths need row locks, which the Ent query builder cannot +// express, so the statements stay raw. +func selectOutboxRows( + ctx context.Context, q entsql.ExecQuerier, query string, args ...any, +) ([]NotificationOutbox, error) { + sqlRows, err := q.QueryContext(ctx, query, args...) + if err != nil { + return nil, err + } + defer sqlRows.Close() + + var out []NotificationOutbox + for sqlRows.Next() { + var ( + row NotificationOutbox + payload []byte + nextAttempt sql.NullTime + lockedBy sql.NullString + lockedAt sql.NullTime + lastError sql.NullString + ) + if err = sqlRows.Scan( + &row.ID, &row.Kind, &row.IncidentID, &row.Recipient, &payload, &row.ChangeID, + &row.DedupKey, &row.Status, &row.Attempts, &nextAttempt, &lockedBy, &lockedAt, + &lastError, &row.CreatedAt, &row.UpdatedAt, + ); err != nil { + return nil, err + } + + if payload != nil { + if err = json.Unmarshal(payload, &row.Payload); err != nil { + return nil, err + } + } + if nextAttempt.Valid { + row.NextAttemptAt = &nextAttempt.Time + } + if lockedBy.Valid { + row.LockedBy = &lockedBy.String + } + if lockedAt.Valid { + row.LockedAt = &lockedAt.Time + } + if lastError.Valid { + row.LastError = &lastError.String + } + + out = append(out, row) } - return db.g.WithContext(ctx).Transaction(func(gtx *gorm.DB) error { - return fn(gtx) - }) + return out, sqlRows.Err() } diff --git a/internal/db/notification_ops.go b/internal/db/notification_ops.go index cbae0c6..dfb3d62 100644 --- a/internal/db/notification_ops.go +++ b/internal/db/notification_ops.go @@ -3,6 +3,10 @@ package db import ( "context" "time" + + entsql "entgo.io/ent/dialect/sql" + + "github.com/stackmon/otc-status-dashboard/ent/notificationoutbox" ) // NotificationStats is a snapshot of the outbox queue for the ops interface. @@ -28,13 +32,21 @@ SELECT COALESCE(SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END), 0) AS processing, COALESCE(SUM(CASE WHEN status = 'sent' THEN 1 ELSE 0 END), 0) AS sent, COALESCE(SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END), 0) AS failed, - COALESCE(SUM(CASE WHEN status = 'processing' AND locked_at < ? THEN 1 ELSE 0 END), 0) AS stale_processing, + COALESCE(SUM(CASE WHEN status = 'processing' AND locked_at < $1 THEN 1 ELSE 0 END), 0) AS stale_processing, COALESCE(SUM(CASE WHEN status = 'pending' AND next_attempt_at > now() THEN 1 ELSE 0 END), 0) AS retry_backlog, COALESCE(EXTRACT(EPOCH FROM now() - MIN(CASE WHEN status IN ('pending', 'processing') THEN created_at END)), 0) AS oldest_pending_age_seconds FROM notification_outbox` - if err := db.g.WithContext(ctx).Raw(query, cutoff).Scan(&stats).Error; err != nil { + if err := db.sql.QueryRowContext(ctx, query, cutoff).Scan( + &stats.Pending, + &stats.Processing, + &stats.Sent, + &stats.Failed, + &stats.StaleProcessing, + &stats.RetryBacklog, + &stats.OldestPendingAgeSeconds, + ); err != nil { return nil, err } return &stats, nil @@ -44,23 +56,36 @@ FROM notification_outbox` // Rows stuck in pending with a rising attempt count are the usual symptom of a // misconfigured relay, so every status must be reachable, not just failed. func (db *DB) ListNotificationsByStatus(ctx context.Context, status string, limit int) ([]NotificationOutbox, error) { - var rows []NotificationOutbox - err := db.g.WithContext(ctx). - Where("status = ?", status). - Order("updated_at DESC"). + rows, err := db.e.NotificationOutbox.Query(). + Where(notificationoutbox.StatusEQ(status)). + Order(notificationoutbox.ByUpdatedAt(entsql.OrderDesc())). Limit(limit). - Find(&rows).Error + All(ctx) if err != nil { return nil, err } - return rows, nil + + out := make([]NotificationOutbox, 0, len(rows)) + for _, row := range rows { + out = append(out, notificationOutboxFromEnt(row)) + } + return out, nil } // EnsureNotificationSchema reports whether the outbox table exists. Migrations are // applied out of band, so without this check a stale database would let the app start // and only fail on the first maintenance change. func (db *DB) EnsureNotificationSchema() error { - if !db.g.Migrator().HasTable(&NotificationOutbox{}) { + var count int + if err := db.sql.QueryRowContext( + context.Background(), + `SELECT count(*) FROM information_schema.tables + WHERE table_schema = CURRENT_SCHEMA() AND table_name = 'notification_outbox' + AND table_type = 'BASE TABLE'`, + ).Scan(&count); err != nil { + return err + } + if count == 0 { return ErrNotificationSchemaMissing } @@ -70,42 +95,53 @@ func (db *DB) EnsureNotificationSchema() error { // RedriveFailed resets failed rows back to pending for another delivery cycle, // clearing attempts, error and lease. With no ids it re-drives every failed row. func (db *DB) RedriveFailed(ctx context.Context, ids ...uint) (int64, error) { - q := db.g.WithContext(ctx).Model(&NotificationOutbox{}).Where("status = ?", NotificationStatusFailed) + update := db.e.NotificationOutbox.Update(). + Where(notificationoutbox.StatusEQ(NotificationStatusFailed)) if len(ids) > 0 { - q = q.Where("id IN ?", ids) + intIDs := make([]int, 0, len(ids)) + for _, id := range ids { + intIDs = append(intIDs, int(id)) + } + update.Where(notificationoutbox.IDIn(intIDs...)) } - res := q.Updates(map[string]any{ - "status": NotificationStatusPending, - "attempts": 0, - "next_attempt_at": time.Now().UTC(), - "last_error": nil, - "locked_by": nil, - "locked_at": nil, - }) - return res.RowsAffected, res.Error + now := time.Now().UTC() + affected, err := update. + SetStatus(NotificationStatusPending). + SetAttempts(0). + SetNextAttemptAt(now). + ClearLastError(). + ClearLockedBy(). + ClearLockedAt(). + SetUpdatedAt(now). + Save(ctx) + return int64(affected), err } // DeleteSentBefore removes delivered rows older than the cutoff in batches // (retention). Failed rows are kept for audit and re-drive. func (db *DB) DeleteSentBefore(ctx context.Context, before time.Time, batchSize int) (int64, error) { + const deleteBatch = `DELETE FROM notification_outbox WHERE id IN ( + SELECT id FROM notification_outbox + WHERE status = $1 AND updated_at < $2 + ORDER BY id LIMIT $3)` + var total int64 for { if ctx.Err() != nil { return total, ctx.Err() } - res := db.g.WithContext(ctx).Exec( - `DELETE FROM notification_outbox WHERE id IN ( - SELECT id FROM notification_outbox - WHERE status = ? AND updated_at < ? - ORDER BY id LIMIT ?)`, - NotificationStatusSent, before, batchSize) - if res.Error != nil { - return total, res.Error + res, err := db.sql.ExecContext(ctx, deleteBatch, NotificationStatusSent, before, batchSize) + if err != nil { + return total, err + } + removed, err := res.RowsAffected() + if err != nil { + return total, err } - total += res.RowsAffected - if res.RowsAffected < int64(batchSize) { + total += removed + if removed < int64(batchSize) { return total, nil } } diff --git a/internal/db/raw.go b/internal/db/raw.go new file mode 100644 index 0000000..34299a5 --- /dev/null +++ b/internal/db/raw.go @@ -0,0 +1,82 @@ +package db + +import ( + "context" + + entsql "entgo.io/ent/dialect/sql" + + "github.com/stackmon/otc-status-dashboard/ent" + "github.com/stackmon/otc-status-dashboard/ent/component" + "github.com/stackmon/otc-status-dashboard/ent/incident" +) + +// incidentsByComponentAttrQuery lists incident ids matched through a component +// attribute, applying the public visibility rules inline. +const incidentsByComponentAttrQuery = ` +SELECT incident.id +FROM incident +JOIN incident_component_relation icr ON icr.incident_id = incident.id +JOIN component_attribute ca ON ca.component_id = icr.component_id +WHERE ca.name = $1 AND ca.value = $2 + AND NOT (incident.type = $3 AND incident.status IN ($4, $5)) + AND NOT (incident.type = $6 AND incident.status = $7 AND NOT EXISTS ( + SELECT 1 FROM incident_status + WHERE incident_status.incident_id = incident.id + AND incident_status.status IN ($8, $9, $10, $11)))` + +func scanIntColumn(ctx context.Context, q entsql.ExecQuerier, query string, args ...any) ([]int, error) { + rows, err := q.QueryContext(ctx, query, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + var values []int + for rows.Next() { + var v int + if err = rows.Scan(&v); err != nil { + return nil, err + } + values = append(values, v) + } + return values, rows.Err() +} + +// incidentsByIDs loads incidents in the given order, repeating entries when the id +// list repeats, with the trimmed component payload the read paths expose. +func (db *DB) incidentsByIDs(ctx context.Context, ids []int) ([]*Incident, error) { + if len(ids) == 0 { + return []*Incident{}, nil + } + + rows, err := db.e.Incident.Query(). + Where(incident.IDIn(ids...)). + WithComponents(func(q *ent.ComponentQuery) { + q.Select(component.FieldID, component.FieldName) + q.WithAttributes() + }). + All(ctx) + if err != nil { + return nil, err + } + + byID := make(map[int]*Incident, len(rows)) + for _, row := range rows { + byID[row.ID] = incidentFromEnt(row) + } + + incidents := make([]*Incident, 0, len(ids)) + for _, id := range ids { + if inc, ok := byID[id]; ok { + incidents = append(incidents, inc) + } + } + + grouped, err := db.statusesByIncident(ctx, ids) + if err != nil { + return nil, err + } + attachStatuses(incidents, grouped) + + return incidents, nil +} diff --git a/internal/db/tx.go b/internal/db/tx.go index 45cf64c..a4ee213 100644 --- a/internal/db/tx.go +++ b/internal/db/tx.go @@ -1,9 +1,95 @@ package db -import "gorm.io/gorm" +import ( + "context" + "database/sql" -// Tx wraps the underlying ORM transaction. Callers pass it through to the + "entgo.io/ent/dialect" + entsql "entgo.io/ent/dialect/sql" + + "github.com/stackmon/otc-status-dashboard/ent" +) + +// Tx wraps the underlying database transaction. Callers pass it through to the // *Tx facade methods and PublishTx; they never call methods on it directly. type Tx struct { - g *gorm.DB + client *ent.Client + driver *sharedTxDriver + sqlTx *sql.Tx +} + +// sharedTxDriver keeps Ent's inner transactions on the connection that already +// started the outer one: edge inserts open a "transaction" of their own, and a +// second database transaction from inside a *sql.Tx is neither possible nor wanted. +type sharedTxDriver struct { + *entsql.Driver +} + +func (d *sharedTxDriver) Tx(context.Context) (dialect.Tx, error) { + return dialect.NopTx(d), nil +} + +// clientFor returns the Ent client bound to tx, or the pool client when tx is nil. +func (db *DB) clientFor(tx *Tx) *ent.Client { + if tx != nil && tx.client != nil { + return tx.client + } + return db.e +} + +// rawFor returns the raw SQL executor scoped to tx, or the pool when tx is nil. +// It keeps hand-written statements (row locks, aggregates) on the same connection +// as the surrounding Ent transaction. +func (db *DB) rawFor(tx *Tx) entsql.ExecQuerier { + if tx != nil && tx.driver != nil { + return tx.driver + } + return db.sql +} + +// begin starts a transaction whose Ent client and raw executor share one connection. +func (db *DB) begin(ctx context.Context) (*Tx, error) { + sqlTx, err := db.sql.BeginTx(ctx, nil) + if err != nil { + return nil, err + } + + driver := &sharedTxDriver{ + Driver: entsql.NewDriver(dialect.Postgres, entsql.Conn{ExecQuerier: sqlTx}), + } + return &Tx{ + client: ent.NewClient(ent.Driver(driver)), + driver: driver, + sqlTx: sqlTx, + }, nil +} + +func (tx *Tx) commit() error { + return tx.sqlTx.Commit() +} + +func (tx *Tx) rollback() error { + return tx.sqlTx.Rollback() +} + +// execWithTx runs fn in a transaction when tx is nil; otherwise it runs on the +// caller's transaction. fn receives the Ent client and the raw executor bound to +// the same transaction. +func (db *DB) execWithTx( + ctx context.Context, tx *Tx, fn func(client *ent.Client, raw entsql.ExecQuerier) error, +) error { + if tx != nil { + return fn(tx.client, tx.driver) + } + + t, err := db.begin(ctx) + if err != nil { + return err + } + defer func() { _ = t.rollback() }() + + if err = fn(t.client, t.driver); err != nil { + return err + } + return t.commit() } diff --git a/internal/db/write.go b/internal/db/write.go new file mode 100644 index 0000000..201c77e --- /dev/null +++ b/internal/db/write.go @@ -0,0 +1,162 @@ +package db + +import ( + "context" + "time" + + "github.com/stackmon/otc-status-dashboard/ent" + "github.com/stackmon/otc-status-dashboard/ent/incident" +) + +func valueOr[T any](p *T, fallback T) T { + if p == nil { + return fallback + } + return *p +} + +// insertIncidentStatus appends one update row. incident_status has no Ent edge to +// incident, so the row is inserted directly and the parent id is supplied by the +// caller when the update does not carry one. +func insertIncidentStatus( + ctx context.Context, c *ent.Client, s *IncidentStatus, fallbackIncidentID uint, +) (int, error) { + now := time.Now().UTC() + createdAt := now + if s.CreatedAt != nil { + createdAt = *s.CreatedAt + } + modifiedAt := now + if s.ModifiedAt != nil { + modifiedAt = *s.ModifiedAt + } + incidentID := s.IncidentID + if incidentID == 0 { + incidentID = fallbackIncidentID + } + + create := c.IncidentStatus.Create(). + SetIncidentID(int(incidentID)). + SetStatus(string(s.Status)). + SetText(s.Text). + SetTimestamp(s.Timestamp). + SetCreatedAt(createdAt). + SetModifiedAt(modifiedAt) + if s.CreatedBy != nil { + create.SetCreatedBy(*s.CreatedBy) + } + if s.ModifiedBy != nil { + create.SetModifiedBy(*s.ModifiedBy) + } + + row, err := create.Save(ctx) + if err != nil { + return 0, err + } + + s.CreatedAt = &createdAt + s.ModifiedAt = &modifiedAt + + return row.ID, nil +} + +// dropIncidentComponent removes a component from the in-memory association list so +// a following full save does not re-insert the join row that was just deleted. +func dropIncidentComponent(inc *Incident, componentID uint) { + kept := inc.Components[:0] + for i := range inc.Components { + if inc.Components[i].ID == componentID { + continue + } + kept = append(kept, inc.Components[i]) + } + inc.Components = kept +} + +// saveIncidentFull writes every incident column and upserts the assocations, which +// is what the previous ORM Save did for these flows: nil optional values clear the +// column instead of being skipped. +func saveIncidentFull(ctx context.Context, c *ent.Client, inc *Incident) error { + update := c.Incident.UpdateOneID(int(inc.ID)). + SetText(valueOr(inc.Text, "")). + SetStartDate(valueOr(inc.StartDate, time.Time{})). + SetImpact(valueOr(inc.Impact, 0)). + SetSystem(inc.System). + SetType(incident.Type(inc.Type)). + SetStatus(string(inc.Status)). + SetVersion(valueOr(inc.Version, 1)) + + if inc.Description != nil { + update.SetDescription(*inc.Description) + } else { + update.ClearDescription() + } + if inc.EndDate != nil { + update.SetEndDate(*inc.EndDate) + } else { + update.ClearEndDate() + } + if inc.CreatedAt != nil { + update.SetCreatedAt(*inc.CreatedAt) + } else { + update.ClearCreatedAt() + } + if inc.ModifiedAt != nil { + update.SetModifiedAt(*inc.ModifiedAt) + } else { + update.ClearModifiedAt() + } + if inc.DeletedAt != nil { + update.SetDeletedAt(*inc.DeletedAt) + } else { + update.ClearDeletedAt() + } + if inc.CreatedBy != nil { + update.SetCreatedBy(*inc.CreatedBy) + } else { + update.ClearCreatedBy() + } + if inc.ContactEmail != nil { + update.SetContactEmail(*inc.ContactEmail) + } else { + update.ClearContactEmail() + } + + if _, err := update.Save(ctx); err != nil { + return err + } + + componentIDs := make([]int, 0, len(inc.Components)) + for i := range inc.Components { + if inc.Components[i].ID != 0 { + componentIDs = append(componentIDs, int(inc.Components[i].ID)) + } + } + if len(componentIDs) > 0 { + if _, err := c.Incident.UpdateOneID(int(inc.ID)).AddComponentIDs(componentIDs...).Save(ctx); err != nil { + return err + } + } + + for i := range inc.Statuses { + if inc.Statuses[i].ID != 0 { + continue + } + id, err := insertIncidentStatus(ctx, c, &inc.Statuses[i], inc.ID) + if err != nil { + return err + } + inc.Statuses[i].ID = uint(id) + inc.Statuses[i].IncidentID = inc.ID + } + + return nil +} + +// removeIncidentComponent deletes only the join row; the component itself stays. +func removeIncidentComponent(ctx context.Context, c *ent.Client, incidentID, componentID uint) error { + _, err := c.Incident.UpdateOneID(int(incidentID)). + RemoveComponentIDs(int(componentID)). + Save(ctx) + return err +} From 22b0af97a4bb1c4a77996fcd38d5a4ffe651f514 Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:27:47 +0200 Subject: [PATCH 05/10] Remove GORM and rewrite the tests that asserted its SQL The handler tests that mocked GORM statements are gone: the field-exposure cases now assert the serialized payload and the rest are covered by the integration suite. Integration helpers use database/sql, and the shared facade handle is closed per test, so the suite no longer exhausts the connection limit. Also fix ListNotificationsByStatus: Ent drops Limit(0) while SQL LIMIT 0 selects nothing, so a zero limit returns no rows and a negative one stays unbounded. --- go.mod | 24 +- go.sum | 77 +-- internal/api/static_test.go | 9 +- internal/api/v2/v2_auth_test.go | 104 +-- internal/api/v2/v2_helpers_test.go | 352 +--------- internal/api/v2/v2_test.go | 957 +--------------------------- internal/db/mock.go | 19 - internal/db/notification_ops.go | 17 +- internal/db/notification_test.go | 2 +- tests/checker_notifications_test.go | 19 +- tests/db_tx_test.go | 18 +- tests/main_test.go | 22 +- tests/notification_worker_test.go | 14 +- tests/notifications_api_test.go | 34 +- tests/notifications_e2e_test.go | 21 +- tests/notifications_ops_test.go | 30 +- tests/notifications_test.go | 34 +- tests/rawdb_test.go | 191 ++++++ tests/rbac_admin_only_test.go | 1 + tests/rbac_helpers_test.go | 1 + 20 files changed, 296 insertions(+), 1650 deletions(-) delete mode 100644 internal/db/mock.go create mode 100644 tests/rawdb_test.go diff --git a/go.mod b/go.mod index 87c7eb5..45d4844 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,14 @@ module github.com/stackmon/otc-status-dashboard go 1.26.0 require ( - github.com/DATA-DOG/go-sqlmock v1.5.2 + entgo.io/ent v0.14.6 github.com/coreos/go-oidc/v3 v3.21.0 github.com/gin-gonic/gin v1.12.0 github.com/golang-jwt/jwt/v5 v5.3.1 github.com/golang-migrate/migrate/v4 v4.20.1 github.com/google/uuid v1.6.0 github.com/gorilla/feeds v1.2.0 + github.com/jackc/pgx/v5 v5.11.0 github.com/joho/godotenv v1.5.1 github.com/kelseyhightower/envconfig v1.4.0 github.com/prometheus/client_golang v1.24.1 @@ -21,16 +22,13 @@ require ( go.uber.org/zap v1.28.0 golang.org/x/sync v0.23.0 gopkg.in/yaml.v3 v3.0.1 - gorm.io/driver/postgres v1.6.3 - gorm.io/gorm v1.31.2 - moul.io/zapgorm2 v1.3.0 ) require ( ariga.io/atlas v0.36.2-0.20250730182955-2c6300d0a3e1 // indirect dario.cat/mergo v1.0.2 // indirect - entgo.io/ent v0.14.6 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect @@ -41,9 +39,6 @@ require ( github.com/bytedance/sonic/loader v0.5.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/clipperhouse/displaywidth v0.6.2 // indirect - github.com/clipperhouse/stringish v0.1.1 // indirect - github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.7 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect @@ -54,7 +49,6 @@ require ( github.com/docker/go-connections v0.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/ebitengine/purego v0.10.1 // indirect - github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.1.0 // indirect github.com/gabriel-vasile/mimetype v1.4.15 // indirect github.com/gin-contrib/sse v1.1.2 // indirect @@ -70,13 +64,9 @@ require ( github.com/goccy/go-yaml v1.19.2 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/hashicorp/hcl/v2 v2.18.1 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.11.0 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.19.2 // indirect github.com/klauspost/cpuid/v2 v2.4.0 // indirect @@ -84,9 +74,7 @@ require ( github.com/lib/pq v1.10.9 // indirect github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect github.com/magiconair/properties v1.8.10 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.24 // indirect - github.com/mattn/go-runewidth v0.0.19 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/go-archive v0.3.0 // indirect @@ -100,10 +88,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect - github.com/olekukonko/errors v1.1.0 // indirect - github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 // indirect - github.com/olekukonko/tablewriter v1.1.3 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pelletier/go-toml/v2 v2.4.3 // indirect @@ -115,8 +99,6 @@ require ( github.com/quic-go/quic-go v0.63.0 // indirect github.com/shirou/gopsutil/v4 v4.26.6 // indirect github.com/sirupsen/logrus v1.9.4 // indirect - github.com/spf13/cobra v1.7.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/tklauser/go-sysconf v0.4.0 // indirect github.com/tklauser/numcpus v0.12.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect diff --git a/go.sum b/go.sum index 8228984..6835806 100644 --- a/go.sum +++ b/go.sum @@ -16,7 +16,6 @@ github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7l github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= @@ -31,12 +30,6 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo= -github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= -github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= -github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= -github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= -github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI= github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -51,7 +44,6 @@ github.com/coreos/go-oidc/v3 v3.21.0 h1:wZo4Q9Pum8dYEj0eMUPrqR+kvuGkeUplbLpNCkBq github.com/coreos/go-oidc/v3 v3.21.0/go.mod h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4= github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,8 +62,6 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/ebitengine/purego v0.10.1 h1:dewVBCBT2GaMu1SrNTYxQhgQBethzfhiwvZiLGP/qyY= github.com/ebitengine/purego v0.10.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc= github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE= github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI= @@ -100,6 +90,8 @@ github.com/go-playground/universal-translator v0.18.2 h1:LCsMLC9RzmbUMNUPVYD15dm github.com/go-playground/universal-translator v0.18.2/go.mod h1:67VZIMp5lQpDWlnStOct22q1bkdJGJqHghbOtmkawxk= github.com/go-playground/validator/v10 v10.30.5 h1:YyCXvVShZbs2Sm3Mb53eNOlhRXctSOzW5QJAouCTZL4= github.com/go-playground/validator/v10 v10.30.5/go.mod h1:wEqiaov48pXX1kjhc3Da8y0M0Dtg/BK7gurFBLgwFrQ= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= @@ -117,8 +109,6 @@ github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo= github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= @@ -127,11 +117,6 @@ github.com/jackc/pgx/v5 v5.11.0 h1:IzBBtyK9AHqf98cctWFifYSci2hgQR/cd56wB4p+ogg= github.com/jackc/pgx/v5 v5.11.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= -github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -143,11 +128,8 @@ github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -160,15 +142,10 @@ github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRt github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= -github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= -github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= +github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI= github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= @@ -200,21 +177,12 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= -github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= -github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= -github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= -github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 h1:jrYnow5+hy3WRDCBypUFvVKNSPPCdqgSXIE9eJDD8LM= -github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= -github.com/olekukonko/tablewriter v1.1.3 h1:VSHhghXxrP0JHl+0NnKid7WoEmd9/urKRJLysb70nnA= -github.com/olekukonko/tablewriter v1.1.3/go.mod h1:9VU0knjhmMkXjnMKrZ3+L2JhhtsQ/L38BbL3CRNE8tM= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY= github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -236,15 +204,12 @@ github.com/quic-go/quic-go v0.63.0 h1:LIFGHI4PFUhhw2dDD1ARHdCff143ffMHwZtbnbuJ78 github.com/quic-go/quic-go v0.63.0/go.mod h1:RAro2j2yN9a9EiPACLHT9IB2NXCvGQmmo/alT0yYI0w= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shirou/gopsutil/v4 v4.26.6 h1:Mzr/npDtQC/xpeEuQKHZt8Zo9CmPvhTj8nkR8w5TLDs= github.com/shirou/gopsutil/v4 v4.26.6/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -275,7 +240,6 @@ github.com/ugorji/go/codec v1.3.2 h1:zkEASHHyEClGeURfgNT9PJZVfAbs9oEX9QXggwWNJbc github.com/ugorji/go/codec v1.3.2/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= github.com/wneessen/go-mail v0.8.1 h1:tVcncj02/QySVFw3zr/kXOzZcuFQqBNT6K+Rbgm/pcM= github.com/wneessen/go-mail v0.8.1/go.mod h1:dWZ61zadzCIyvB4y1/YzC5O7MrbbzBfPkARmbosdf8w= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= @@ -299,17 +263,12 @@ go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRk go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c= go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= @@ -319,20 +278,14 @@ go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/arch v0.31.0 h1:22MlEb14/O/EPCYHFxsDdv5TuLD5dMjT5e2QeJw4ULk= golang.org/x/arch v0.31.0/go.mod h1:KcJSod3cqT2dKcjBxqTyGfbumNikqU9p5tHJinPJnuY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues= @@ -340,17 +293,13 @@ golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= golang.org/x/oauth2 v0.37.0 h1:JUlcxA8oAtauLfiH8FX2/FkAWHAdi0QtGCGc+hofE98= golang.org/x/oauth2 v0.37.0/go.mod h1:IxwZNxUULJmpBFf9K/9NTMSIfZZuvuTy1gGxhigP/58= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -371,36 +320,20 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.6.3 h1:bAn6O2pUa8LtpWEvL5NFU4+52Tfx8Ut7IVaIacCLcI0= -gorm.io/driver/postgres v1.6.3/go.mod h1:0c4fQA44XhOklXDkgtuKqysHCycTa5i9e3EIpDGCwXk= -gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= -gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= -gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.31.2 h1:3o8FXNo9v9S858gil+3LlZA1LkCOzgb4g5BL64FgaCo= -gorm.io/gorm v1.31.2/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -moul.io/zapgorm2 v1.3.0 h1:+CzUTMIcnafd0d/BvBce8T4uPn6DQnpIrz64cyixlkk= -moul.io/zapgorm2 v1.3.0/go.mod h1:nPVy6U9goFKHR4s+zfSo1xVFaoU7Qgd5DoCdOfzoCqs= pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= diff --git a/internal/api/static_test.go b/internal/api/static_test.go index a73c53f..5ca59cf 100644 --- a/internal/api/static_test.go +++ b/internal/api/static_test.go @@ -14,6 +14,9 @@ import ( "github.com/stackmon/otc-status-dashboard/internal/db" ) +// unreachableDSN lets tests build a *db.DB without opening a connection. +const unreachableDSN = "postgres://postgres:postgres@127.0.0.1:1/postgres?sslmode=disable" + const staticTestSpec = `openapi: 3.0.0 info: title: status dashboard @@ -28,8 +31,9 @@ func newStaticRouter(t *testing.T, staticCfg conf.Static) *gin.Engine { idp := newTestIDP(t) - database, _, err := db.NewWithMock() + database, err := db.New(&conf.Config{DB: unreachableDSN}) require.NoError(t, err) + t.Cleanup(func() { _ = database.Close() }) cfg := &conf.Config{ Port: "8000", @@ -72,8 +76,9 @@ func TestCatchAllWithoutStaticOrigins(t *testing.T) { func TestNewRejectsUnusableStaticConfiguration(t *testing.T) { idp := newTestIDP(t) - database, _, err := db.NewWithMock() + database, err := db.New(&conf.Config{DB: unreachableDSN}) require.NoError(t, err) + t.Cleanup(func() { _ = database.Close() }) cfg := &conf.Config{ Port: "8000", diff --git a/internal/api/v2/v2_auth_test.go b/internal/api/v2/v2_auth_test.go index 6407219..1b82066 100644 --- a/internal/api/v2/v2_auth_test.go +++ b/internal/api/v2/v2_auth_test.go @@ -1,110 +1,58 @@ package v2 import ( - "net/http" - "net/http/httptest" + "encoding/json" "testing" "time" - "github.com/DATA-DOG/go-sqlmock" - "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.uber.org/zap" - "github.com/stackmon/otc-status-dashboard/internal/api/rbac" "github.com/stackmon/otc-status-dashboard/internal/db" ) -func TestCreatorFieldExposedToAuthenticated(t *testing.T) { - d, m, err := db.NewWithMock() - require.NoError(t, err) - log := zap.NewNop() +func maintenanceIncident(createdBy, contactEmail *string) *db.Incident { + text := "Title" + start := time.Now().UTC() + impact := 1 + return &db.Incident{ + Text: &text, + StartDate: &start, + Impact: &impact, + Type: "maintenance", + CreatedBy: createdBy, + ContactEmail: contactEmail, + } +} - now := time.Now().UTC() +func TestCreatorFieldExposedToAuthenticated(t *testing.T) { creator := "user@example.com" contactEmail := "contact@example.com" - m.ExpectQuery(`^SELECT count\(\*\) FROM "incident"`).WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) - - rowsInc := sqlmock.NewRows([]string{"id", "text", "description", "start_date", "end_date", "impact", "system", "type", "created_by", "contact_email"}). - AddRow(1, "Title", "Desc", now, now.Add(1*time.Hour), 1, false, "maintenance", creator, contactEmail) - m.ExpectQuery(`^SELECT (.+) FROM "incident"`).WillReturnRows(rowsInc) - - m.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`).WillReturnRows(sqlmock.NewRows([]string{"incident_id", "component_id"})) - m.ExpectQuery(`^SELECT (.+) FROM "incident_status"`).WillReturnRows(sqlmock.NewRows([]string{"id", "incident_id", "timestamp", "text", "status"})) - - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Request, _ = http.NewRequest(http.MethodGet, "/v2/events", nil) - - c.Set("userIDRoles", []string{"operators"}) - - handler := GetEventsHandler(d, log, rbac.New(rbac.Config{Operators: "operators"})) - handler(c) + body, err := json.Marshal(toAPIEvent(maintenanceIncident(&creator, &contactEmail), true)) + require.NoError(t, err) - assert.Equal(t, 200, w.Code) - assert.Contains(t, w.Body.String(), `"creator":"user@example.com"`) + assert.Contains(t, string(body), `"creator":"user@example.com"`) } func TestCreatorFieldHiddenFromUnauthenticated(t *testing.T) { - d, m, err := db.NewWithMock() - require.NoError(t, err) - log := zap.NewNop() - - now := time.Now().UTC() creator := "user@example.com" - contactEmail := "contact@example.com" - m.ExpectQuery(`^SELECT count\(\*\) FROM "incident"`).WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) - - rowsInc := sqlmock.NewRows([]string{"id", "text", "description", "start_date", "end_date", "impact", "system", "type", "created_by", "contact_email"}). - AddRow(1, "Title", "Desc", now, now.Add(1*time.Hour), 1, false, "maintenance", creator, contactEmail) - m.ExpectQuery(`^SELECT (.+) FROM "incident"`).WillReturnRows(rowsInc) - - m.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`).WillReturnRows(sqlmock.NewRows([]string{"incident_id", "component_id"})) - m.ExpectQuery(`^SELECT (.+) FROM "incident_status"`).WillReturnRows(sqlmock.NewRows([]string{"id", "incident_id", "timestamp", "text", "status"})) - - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Request, _ = http.NewRequest(http.MethodGet, "/v2/events", nil) - - handler := GetEventsHandler(d, log, rbac.New(rbac.Config{Operators: "operators"})) - handler(c) + body, err := json.Marshal(toAPIEvent(maintenanceIncident(&creator, nil), false)) + require.NoError(t, err) - assert.Equal(t, 200, w.Code) - assert.NotContains(t, w.Body.String(), "creator") - assert.NotContains(t, w.Body.String(), "user@example.com") + assert.NotContains(t, string(body), "creator") + assert.NotContains(t, string(body), "user@example.com") } func TestContactEmailHiddenFromUnauthenticated(t *testing.T) { - d, m, err := db.NewWithMock() - require.NoError(t, err) - log := zap.NewNop() - - now := time.Now().UTC() - creator := "user@example.com" contactEmail := "contact@example.com" - m.ExpectQuery(`^SELECT count\(\*\) FROM "incident"`).WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) - - rowsInc := sqlmock.NewRows([]string{"id", "text", "description", "start_date", "end_date", "impact", "system", "type", "created_by", "contact_email"}). - AddRow(1, "Title", "Desc", now, now.Add(1*time.Hour), 1, false, "maintenance", creator, contactEmail) - m.ExpectQuery(`^SELECT (.+) FROM "incident"`).WillReturnRows(rowsInc) - - m.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`).WillReturnRows(sqlmock.NewRows([]string{"incident_id", "component_id"})) - m.ExpectQuery(`^SELECT (.+) FROM "incident_status"`).WillReturnRows(sqlmock.NewRows([]string{"id", "incident_id", "timestamp", "text", "status"})) - - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Request, _ = http.NewRequest(http.MethodGet, "/v2/events", nil) - - handler := GetEventsHandler(d, log, rbac.New(rbac.Config{Operators: "operators"})) - handler(c) + body, err := json.Marshal(toAPIEvent(maintenanceIncident(nil, &contactEmail), false)) + require.NoError(t, err) - assert.Equal(t, 200, w.Code) - assert.NotContains(t, w.Body.String(), "contact_email") - assert.NotContains(t, w.Body.String(), "contact@example.com") + assert.NotContains(t, string(body), "contact_email") + assert.NotContains(t, string(body), "contact@example.com") } func TestVersionFieldExposedToAuthenticated(t *testing.T) { diff --git a/internal/api/v2/v2_helpers_test.go b/internal/api/v2/v2_helpers_test.go index d3e9298..829e4d0 100644 --- a/internal/api/v2/v2_helpers_test.go +++ b/internal/api/v2/v2_helpers_test.go @@ -1,262 +1,19 @@ package v2 import ( - "database/sql/driver" - "errors" "testing" - "time" - "github.com/DATA-DOG/go-sqlmock" "github.com/gin-gonic/gin" "github.com/stretchr/testify/require" "go.uber.org/zap" - apiErrors "github.com/stackmon/otc-status-dashboard/internal/api/errors" - "github.com/stackmon/otc-status-dashboard/internal/api/rbac" + "github.com/stackmon/otc-status-dashboard/internal/conf" "github.com/stackmon/otc-status-dashboard/internal/db" ) -func initTests(t *testing.T) (*gin.Engine, sqlmock.Sqlmock, *db.DB) { - t.Helper() - - t.Log("start initialisation") - d, m, err := db.NewWithMock() - require.NoError(t, err) - - gin.SetMode(gin.TestMode) - r := gin.Default() - r.NoRoute(apiErrors.Return404) - - log, _ := zap.NewDevelopment() - initRoutes(t, r, d, log) - - return r, m, d -} - -func initRoutes(t *testing.T, c *gin.Engine, dbInst *db.DB, log *zap.Logger) { - t.Helper() - - // Middleware to inject admin role for tests - setAdminRole := func(c *gin.Context) { - c.Set("role", rbac.Admin) - c.Next() - } - - v2Api := c.Group("v2") - { - v2Api.GET("components", GetComponentsHandler(dbInst, log)) - v2Api.GET("components/:id", GetComponentHandler(dbInst, log)) - v2Api.GET("component_status", GetComponentsHandler(dbInst, log)) - v2Api.POST("component_status", PostComponentHandler(dbInst, log)) - - // Incidents routes (deprecated) - v2Api.GET("incidents", GetIncidentsHandler(dbInst, log, rbac.New(rbac.Config{Operators: "operators"}))) - v2Api.POST("incidents", PostIncidentHandler(dbInst, log)) - v2Api.GET("incidents/:eventID", GetIncidentHandler(dbInst, log, rbac.New(rbac.Config{Operators: "operators"}))) - v2Api.PATCH("incidents/:eventID", - EventExistenceCheckForTests(dbInst, log), - setAdminRole, - PatchIncidentHandler(dbInst, log)) - v2Api.PATCH("incidents/:eventID/updates/:updateID", - EventExistenceCheckForTests(dbInst, log), - PatchEventUpdateTextHandler(dbInst, log), - ) - - // Events routes (new endpoints) - v2Api.GET("events", GetEventsHandler(dbInst, log, rbac.New(rbac.Config{Operators: "operators"}))) - v2Api.POST("events", PostIncidentHandler(dbInst, log)) - v2Api.GET("events/:eventID", GetIncidentHandler(dbInst, log, rbac.New(rbac.Config{Operators: "operators"}))) - v2Api.PATCH("events/:eventID", - EventExistenceCheckForTests(dbInst, log), - setAdminRole, - PatchIncidentHandler(dbInst, log)) - v2Api.PATCH("events/:eventID/updates/:updateID", - EventExistenceCheckForTests(dbInst, log), - PatchEventUpdateTextHandler(dbInst, log), - ) - - v2Api.GET("availability", GetComponentsAvailabilityHandler(dbInst, log)) - } -} - -func prepareIncident(t *testing.T, mock sqlmock.Sqlmock, testTime time.Time) { - t.Helper() - - mock.ExpectQuery(`^SELECT count\(\*\) FROM "incident"`). - WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(2)) - - rowsInc := sqlmock.NewRows([]string{"id", "text", "description", "start_date", "end_date", "impact", "system", "type", "created_by", "contact_email"}). - AddRow(1, "Incident title A", "Description A", testTime, testTime.Add(time.Hour*72), 0, false, "maintenance", nil, nil). - AddRow(2, "Incident title B", "Description B", testTime, testTime.Add(time.Hour*72), 3, false, "incident", nil, nil) - mock.ExpectQuery(`^SELECT (.+) FROM "incident"`).WillReturnRows(rowsInc) - - rowsIncComp := sqlmock.NewRows([]string{"incident_id", "component_id"}). - AddRow(1, 150). - AddRow(2, 151) - mock.ExpectQuery("^SELECT (.+) FROM \"incident_component_relation\"(.+)").WillReturnRows(rowsIncComp) - - rowsComp := sqlmock.NewRows([]string{"id", "name"}). - AddRow(150, "Component A"). - AddRow(151, "Component B") - mock.ExpectQuery("^SELECT (.+) FROM \"component\"(.+)").WillReturnRows(rowsComp) - - rowsCompAttr := sqlmock.NewRows([]string{"id", "component_id", "name", "value"}). - AddRows([][]driver.Value{ - {859, 150, "category", "A"}, - {860, 150, "region", "A"}, - {861, 150, "type", "b"}, - {862, 151, "category", "B"}, - {863, 151, "region", "B"}, - {864, 151, "type", "a"}, - }...) - mock.ExpectQuery("^SELECT (.+) FROM \"component_attribute\"").WillReturnRows(rowsCompAttr) - - rowsStatus := sqlmock.NewRows([]string{"id", "incident_id", "timestamp", "text", "status"}). - AddRow(1, 1, testTime.Add(time.Hour*72), "Issue solved.", "resolved"). - AddRow(2, 2, testTime.Add(time.Hour*72), "Issue solved.", "resolved") - mock.ExpectQuery("^SELECT (.+) FROM \"incident_status\"").WillReturnRows(rowsStatus) - - mock.NewRowsWithColumnDefinition() -} - -func prepareIncidentRows(result []*db.Incident) (*sqlmock.Rows, []driver.Value, []driver.Value) { - incidentIDs := make([]driver.Value, len(result)) - componentIDs := make([]driver.Value, 0) - rowsInc := sqlmock.NewRows([]string{"id", "text", "description", "start_date", "end_date", "impact", "system", "type", "created_by", "contact_email", "version"}) - - for i, inc := range result { - incidentIDs[i] = inc.ID - var descriptionVal interface{} - if inc.Description != nil { - descriptionVal = *inc.Description - } - var versionVal interface{} - if inc.Version != nil { - versionVal = *inc.Version - } else { - versionVal = 1 // default version - } - rowsInc.AddRow(inc.ID, *inc.Text, descriptionVal, *inc.StartDate, inc.EndDate, *inc.Impact, inc.System, inc.Type, inc.CreatedBy, inc.ContactEmail, versionVal) - for _, comp := range inc.Components { - componentIDs = append(componentIDs, comp.ID) - } - } - return rowsInc, incidentIDs, componentIDs -} - -func prepareRelatedRows(result []*db.Incident) (*sqlmock.Rows, *sqlmock.Rows, *sqlmock.Rows, *sqlmock.Rows) { - rowsIncComp := sqlmock.NewRows([]string{"incident_id", "component_id"}) - rowsComp := sqlmock.NewRows([]string{"id", "name"}) - rowsCompAttr := sqlmock.NewRows([]string{"id", "component_id", "name", "value"}) - rowsStatus := sqlmock.NewRows([]string{"id", "incident_id", "timestamp", "text", "status"}) - - for _, inc := range result { - for _, comp := range inc.Components { - rowsIncComp.AddRow(inc.ID, comp.ID) - rowsComp.AddRow(comp.ID, comp.Name) - for _, attr := range comp.Attrs { - rowsCompAttr.AddRow(attr.ID, attr.ComponentID, attr.Name, attr.Value) - } - } - for _, status := range inc.Statuses { - rowsStatus.AddRow(status.ID, status.IncidentID, status.Timestamp, status.Text, status.Status) - } - } - return rowsIncComp, rowsComp, rowsCompAttr, rowsStatus -} - -func prepareMockForIncidents(t *testing.T, mock sqlmock.Sqlmock, result []*db.Incident) { - t.Helper() - - if len(result) == 0 { - mock.ExpectQuery(`^SELECT count\(\*\) FROM "incident"`). - WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0)) - mock.ExpectQuery(`^SELECT (.+) FROM "incident"`). - WillReturnRows(sqlmock.NewRows([]string{"id", "text", "description", "start_date", "end_date", "impact", "system", "type", "created_by", "contact_email"})) - return - } - - mock.ExpectQuery(`^SELECT count\(\*\) FROM "incident"`). - WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(len(result))) - - rowsInc, incidentIDs, componentIDs := prepareIncidentRows(result) - mock.ExpectQuery(`^SELECT (.+) FROM "incident"`). - WillReturnRows(rowsInc) - - rowsIncComp, rowsComp, rowsCompAttr, rowsStatus := prepareRelatedRows(result) - - mock.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`).WithArgs(incidentIDs...).WillReturnRows(rowsIncComp) - mock.ExpectQuery(`^SELECT (.+) FROM "component"`).WithArgs(componentIDs...).WillReturnRows(rowsComp) - mock.ExpectQuery("^SELECT (.+) FROM \"component_attribute\"").WillReturnRows(rowsCompAttr) - mock.ExpectQuery(`^SELECT (.+) FROM "incident_status"`).WithArgs(incidentIDs...).WillReturnRows(rowsStatus) -} - -func prepareMockForEvents(t *testing.T, mock sqlmock.Sqlmock, result []*db.Incident, totalCount int) { - t.Helper() - - mock.ExpectQuery(`^SELECT count\(\*\) FROM "incident"`). - WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(totalCount)) - - if len(result) == 0 { - mock.ExpectQuery(`^SELECT (.+) FROM "incident"`). - WillReturnRows(sqlmock.NewRows([]string{"id", "text", "description", "start_date", "end_date", "impact", "system", "type", "created_by", "contact_email"})) - return - } - - rowsInc, incidentIDs, componentIDs := prepareIncidentRows(result) - mock.ExpectQuery(`^SELECT (.+) FROM "incident"`). - WillReturnRows(rowsInc) - - rowsIncComp, rowsComp, rowsCompAttr, rowsStatus := prepareRelatedRows(result) - - mock.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`). - WithArgs(incidentIDs...). - WillReturnRows(rowsIncComp) - - uniqueComponentIDs := make(map[driver.Value]bool) - for _, id := range componentIDs { - uniqueComponentIDs[id] = true - } - if len(uniqueComponentIDs) > 0 { - mock.ExpectQuery(`^SELECT (.+) FROM "component"`).WillReturnRows(rowsComp) - } - - mock.ExpectQuery("^SELECT (.+) FROM \"component_attribute\"").WillReturnRows(rowsCompAttr) - mock.ExpectQuery(`^SELECT (.+) FROM "incident_status"`).WithArgs(incidentIDs...).WillReturnRows(rowsStatus) -} - -func prepareAvailability(t *testing.T, mock sqlmock.Sqlmock, testTime time.Time) { - t.Helper() - - rowsComp := sqlmock.NewRows([]string{"id", "name"}). - AddRow(151, "Component B") - mock.ExpectQuery("^SELECT (.+) FROM \"component\"$").WillReturnRows(rowsComp) - - rowsCompAttr := sqlmock.NewRows([]string{"id", "component_id", "name", "value"}). - AddRows([][]driver.Value{ - {862, 151, "category", "B"}, - {863, 151, "region", "B"}, - {864, 151, "type", "a"}, - }...) - mock.ExpectQuery("^SELECT (.+) FROM \"component_attribute\"").WillReturnRows(rowsCompAttr) - - rowsIncComp := sqlmock.NewRows([]string{"incident_id", "component_id"}). - AddRow(2, 151) - mock.ExpectQuery("^SELECT (.+) FROM \"incident_component_relation\"(.+)").WillReturnRows(rowsIncComp) - - startOfMonth := time.Date(testTime.Year(), testTime.Month(), 1, 0, 0, 0, 0, time.UTC) - startOfNextMonth := startOfMonth.AddDate(0, 1, 0) - - rowsInc := sqlmock.NewRows([]string{"id", "text", "description", "start_date", "end_date", "impact", "system", "type", "created_by", "contact_email"}). - AddRow(2, "Incident title B", "Description B for Availability", startOfMonth, startOfNextMonth, 3, false, "incident", nil, nil) - mock.ExpectQuery("^SELECT (.+) FROM \"incident\" WHERE \"incident\".\"id\" = \\$1$").WillReturnRows(rowsInc) - - rowsStatus := sqlmock.NewRows([]string{"id", "incident_id", "timestamp", "text", "status"}). - AddRow(2, 2, testTime.Add(time.Hour*72), "Issue solved.", "resolved") - mock.ExpectQuery("^SELECT (.+) FROM \"incident_status\"").WillReturnRows(rowsStatus) - - mock.NewRowsWithColumnDefinition() -} +// unreachableDSN lets tests build a *db.DB without opening a connection; the +// handler paths they exercise reject the request before any query runs. +const unreachableDSN = "postgres://postgres:postgres@127.0.0.1:1/postgres?sslmode=disable" func getYearAndMonth(year, month, offset int) (int, int) { newMonth := month - offset @@ -267,85 +24,15 @@ func getYearAndMonth(year, month, offset int) (int, int) { return year, newMonth } -func prepareMockForPatchEventUpdate(t *testing.T, mock sqlmock.Sqlmock, incident *db.Incident, updateID uint, updatedText string, updateIndex int) { - t.Helper() - - // First mock for GetIncident in EventExistenceCheck middleware - rowsInc, incidentIDs, componentIDs := prepareIncidentRows([]*db.Incident{incident}) - mock.ExpectQuery(`^SELECT (.+) FROM "incident"`).WillReturnRows(rowsInc) - - rowsIncComp, rowsComp, rowsCompAttr, rowsStatus := prepareRelatedRows([]*db.Incident{incident}) - - mock.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`). - WithArgs(incidentIDs...). - WillReturnRows(rowsIncComp) - mock.ExpectQuery(`^SELECT (.+) FROM "component"`). - WithArgs(componentIDs...). - WillReturnRows(rowsComp) - mock.ExpectQuery("^SELECT (.+) FROM \"component_attribute\""). - WillReturnRows(rowsCompAttr) - mock.ExpectQuery(`^SELECT (.+) FROM "incident_status"`). - WithArgs(incidentIDs...). - WillReturnRows(rowsStatus) - - // Second mock for GetEventUpdates in handler - get all updates - statusRows := sqlmock.NewRows([]string{"id", "incident_id", "status", "text", "timestamp"}) - for _, status := range incident.Statuses { - statusRows.AddRow(status.ID, status.IncidentID, status.Status, status.Text, status.Timestamp) - } - mock.ExpectQuery(`^SELECT \* FROM "incident_status" WHERE incident_id = \$1`). - WithArgs(incident.ID). - WillReturnRows(statusRows) - - // Get target update by index - targetStatus := incident.Statuses[updateIndex] - - // Mock for update transaction - returningRows := sqlmock.NewRows([]string{"id", "incident_id", "status", "text", "timestamp"}) - returningRows.AddRow(targetStatus.ID, targetStatus.IncidentID, targetStatus.Status, updatedText, targetStatus.Timestamp) - - mock.ExpectBegin() - mock.ExpectQuery(`^UPDATE "incident_status" SET "modified_at"=\$1,"text"=\$2 WHERE id = \$3 AND incident_id = \$4 RETURNING .*`). - WithArgs(sqlmock.AnyArg(), updatedText, targetStatus.ID, incident.ID). - WillReturnRows(returningRows) - mock.ExpectCommit() - - // Mock for Scan(&updated) - returningRows = sqlmock.NewRows([]string{"id", "incident_id", "status", "text", "timestamp"}) - returningRows.AddRow(targetStatus.ID, targetStatus.IncidentID, targetStatus.Status, updatedText, targetStatus.Timestamp) - mock.ExpectQuery(`^SELECT \* FROM "incident_status" WHERE id = \$1 AND incident_id = \$2`). - WithArgs(updateID, incident.ID). - WillReturnRows(returningRows) -} - -func prepareMockForModifyEventUpdate( - t *testing.T, - mock sqlmock.Sqlmock, - status db.IncidentStatus, - updatedText string, - modifiedAt time.Time, -) { - t.Helper() - - mock.ExpectBegin() - - returningRows := sqlmock.NewRows([]string{"id", "incident_id", "text", "status", "timestamp", "created_at", "modified_at"}). - AddRow(status.ID, status.IncidentID, updatedText, status.Status, status.Timestamp, status.CreatedAt, modifiedAt) - mock.ExpectQuery(`^UPDATE "incident_status" SET "modified_at"=\$1,"text"=\$2 WHERE id = \$3 AND incident_id = \$4 RETURNING .*`). - WithArgs(sqlmock.AnyArg(), updatedText, status.ID, status.IncidentID). - WillReturnRows(returningRows) - - mock.ExpectCommit() -} - // initRouterWithStoredEvent returns a *gin.Engine with a single PATCH /v2/events/:eventID route // that injects the given incident into the gin context (simulating CheckEventExistenceMW) so that // PatchIncidentHandler can be exercised without a real database lookup. func initRouterWithStoredEvent(t *testing.T, incident *db.Incident) *gin.Engine { t.Helper() - d, _, err := db.NewWithMock() + d, err := db.New(&conf.Config{DB: unreachableDSN}) require.NoError(t, err) + t.Cleanup(func() { _ = d.Close() }) gin.SetMode(gin.TestMode) r := gin.New() @@ -358,30 +45,3 @@ func initRouterWithStoredEvent(t *testing.T, incident *db.Incident) *gin.Engine return r } - -// EventExistenceCheckForTests duplicates logic from api.EventExistenceCheck but exists in package v2 tests. -func EventExistenceCheckForTests(dbInst *db.DB, _ *zap.Logger) gin.HandlerFunc { - return func(c *gin.Context) { - var uri struct { - ID uint `uri:"eventID" binding:"required"` - } - if err := c.ShouldBindUri(&uri); err != nil { - apiErrors.RaiseBadRequestErr(c, err) - return - } - - event, err := dbInst.GetIncident(int(uri.ID)) - if err != nil { - if errors.Is(err, db.ErrDBIncidentDSNotExist) { - apiErrors.RaiseStatusNotFoundErr(c, apiErrors.ErrIncidentDSNotExist) - return - } - apiErrors.RaiseInternalErr(c, err) - return - } - - // Set event in context so PatchIncidentHandler can access it - c.Set("event", event) - c.Next() - } -} diff --git a/internal/api/v2/v2_test.go b/internal/api/v2/v2_test.go index d3d6448..705bd07 100644 --- a/internal/api/v2/v2_test.go +++ b/internal/api/v2/v2_test.go @@ -1,7 +1,6 @@ package v2 import ( - "encoding/json" "fmt" "net/http" "net/http/httptest" @@ -9,7 +8,7 @@ import ( "testing" "time" - "github.com/DATA-DOG/go-sqlmock" + "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -18,298 +17,11 @@ import ( "github.com/stackmon/otc-status-dashboard/internal/event" ) -func TestGetIncidentsHandler(t *testing.T) { - r, m, _ := initTests(t) - - startDate := "2024-09-01T11:45:26.371Z" - endDate := "2024-09-04T11:45:26.371Z" - - testTime, err := time.Parse(time.RFC3339, startDate) - require.NoError(t, err) - - prepareIncident(t, m, testTime) - - var response = `{"data":[{"id":1,"title":"Incident title A","description":"Description A","impact":0,"components":[150],"start_date":"%s","end_date":"%s","system":false,"type":"maintenance","updates":[{"id":0,"status":"resolved","text":"Issue solved.","timestamp":"%s"}]},{"id":2,"title":"Incident title B","description":"Description B","impact":3,"components":[151],"start_date":"%s","end_date":"%s","system":false,"type":"incident","updates":[{"id":0,"status":"resolved","text":"Issue solved.","timestamp":"%s"}]}]}` - - w := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodGet, "/v2/incidents", nil) - - r.ServeHTTP(w, req) - - assert.Equal(t, 200, w.Code) - assert.Equal(t, fmt.Sprintf(response, startDate, endDate, endDate, startDate, endDate, endDate), w.Body.String()) -} - -func TestGetIncidentsHandlerFilters(t *testing.T) { - startDate := "2025-03-01T11:45:26.371Z" - endDate := "2025-03-04T11:45:26.371Z" - testTime, err := time.Parse(time.RFC3339, startDate) - require.NoError(t, err) - testEndTime, err := time.Parse(time.RFC3339, endDate) - require.NoError(t, err) - - impact0 := 0 - impact3 := 3 - systemFalse := false - systemTrue := true - - // Mock data setup - incidentA := db.Incident{ - ID: 1, - Text: &[]string{"Incident title A"}[0], - Description: &[]string{"Description A"}[0], - StartDate: &testTime, - EndDate: &testEndTime, - Impact: &impact0, // Maintenance - Type: event.TypeMaintenance, - System: systemFalse, - Components: []db.Component{ - { - ID: 150, - Name: "Component A", - Attrs: []db.ComponentAttr{ - {ID: 859, ComponentID: 150, Name: "category", Value: "A"}, - {ID: 860, ComponentID: 150, Name: "region", Value: "A"}, - {ID: 861, ComponentID: 150, Name: "type", Value: "b"}, - }, - }, - }, - Statuses: []db.IncidentStatus{{ID: 1, IncidentID: 1, Timestamp: testEndTime, Text: "Maintenance completed.", Status: "completed"}}, - } - incidentB := db.Incident{ - ID: 2, - Text: &[]string{"Incident title B"}[0], - Description: &[]string{"Description B"}[0], - StartDate: &testTime, - EndDate: nil, // IsActive - Impact: &impact3, // Incident - Type: event.TypeIncident, - System: systemTrue, - Components: []db.Component{ - { - ID: 151, - Name: "Component B", - Attrs: []db.ComponentAttr{ - {ID: 862, ComponentID: 151, Name: "category", Value: "B"}, - {ID: 863, ComponentID: 151, Name: "region", Value: "B"}, - {ID: 864, ComponentID: 151, Name: "type", Value: "a"}, - }, - }, - }, - Statuses: []db.IncidentStatus{{ID: 2, IncidentID: 2, Timestamp: testTime, Text: "Incident analysing.", Status: "analysing"}}, - } - - // Expected JSON responses (simplified for brevity) - responseA := fmt.Sprintf(`{"data":[{"id":1,"title":"Incident title A","description":"Description A","impact":0,"components":[150],"start_date":"%s","end_date":"%s","system":false,"type":"maintenance","updates":[{"id":0,"status":"completed","text":"Maintenance completed.","timestamp":"%s"}]}]}`, startDate, endDate, endDate) - responseB := fmt.Sprintf(`{"data":[{"id":2,"title":"Incident title B","description":"Description B","impact":3,"components":[151],"start_date":"%s","system":true,"type":"incident","updates":[{"id":0,"status":"analysing","text":"Incident analysing.","timestamp":"%s"}]}]}`, startDate, startDate) - responseEmpty := `{"data":[]}` - isActiveTrue := true - - testCases := []struct { - name string - url string - mockSetup func(m sqlmock.Sqlmock, params *db.IncidentsParams) - expectedStatus int - expectedBody string - }{ - { - name: "Filter by type=maintenance", - url: "/v2/incidents?type=maintenance", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.Types = []string{event.TypeMaintenance} - prepareMockForIncidents(t, m, []*db.Incident{&incidentA}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseA, - }, - { - name: "Filter by type=incident", - url: "/v2/incidents?type=incident", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.Types = []string{event.TypeIncident} - prepareMockForIncidents(t, m, []*db.Incident{&incidentB}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseB, - }, - { - name: "Filter by opened=true", - url: "/v2/incidents?opened=true", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.IsActive = &isActiveTrue - prepareMockForIncidents(t, m, []*db.Incident{&incidentB}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseB, - }, - { - name: "Filter by active=false", - url: "/v2/incidents?active=false", - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, // No DB call expected - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Filter by impact=3", - url: "/v2/incidents?impact=3", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.Impact = &impact3 - prepareMockForIncidents(t, m, []*db.Incident{&incidentB}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseB, - }, - { - name: "Filter by system=true", - url: "/v2/incidents?system=true", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.IsSystem = &systemTrue - prepareMockForIncidents(t, m, []*db.Incident{&incidentB}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseB, - }, - { - name: "Filter by components=151", - url: "/v2/incidents?components=151", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.ComponentIDs = []int{151} - prepareMockForIncidents(t, m, []*db.Incident{&incidentB}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseB, - }, - { - name: "Filter by status=analysing", - url: "/v2/incidents?status=analysing", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.Status = &incidentB.Statuses[0].Status - prepareMockForIncidents(t, m, []*db.Incident{&incidentB}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseB, - }, - { - name: "Filter combination: type=incident&active=true", - url: "/v2/incidents?type=incident&active=true", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.Types = []string{event.TypeIncident} - params.IsActive = &isActiveTrue - prepareMockForIncidents(t, m, []*db.Incident{&incidentB}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseB, - }, - { - name: "Filter combination: status=analysing&impact=3", - url: "/v2/incidents?status=analysing&impact=3", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.Status = &incidentB.Statuses[0].Status - prepareMockForIncidents(t, m, []*db.Incident{&incidentB}) - }, - expectedStatus: http.StatusOK, - expectedBody: responseB, - }, - { - name: "Filter wrong status paramter: status=resurrected", - url: "/v2/incidents?status=resurrected", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - params.Status = &incidentB.Statuses[0].Status - prepareMockForIncidents(t, m, []*db.Incident{}) - }, - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Filter combination: no results", - url: "/v2/incidents?impact=1", - mockSetup: func(m sqlmock.Sqlmock, params *db.IncidentsParams) { - impact1 := 1 - params.Impact = &impact1 - prepareMockForIncidents(t, m, []*db.Incident{}) // Empty slice - }, - expectedStatus: http.StatusOK, - expectedBody: responseEmpty, - }, - { - name: "Invalid filter: type=invalid", - url: "/v2/incidents?type=invalid", - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, // No DB call expected - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Invalid filter: active=maybe", - url: "/v2/incidents?active=maybe", - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Invalid filter: active=false", - url: "/v2/incidents?active=false", - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Invalid filter: impact=abc", - url: "/v2/incidents?impact=abc", - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Invalid filter: impact=5", - url: "/v2/incidents?impact=5", - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Invalid filter: components=abc", - url: "/v2/incidents?components=abc", - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Invalid filter: components=2147483649", - url: "/v2/incidents?components=2147483649", - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - { - name: "Invalid filter: start_date after end_date", - url: fmt.Sprintf("/v2/incidents?start_date=%s&end_date=%s", endDate, startDate), // Swapped start and end dates - mockSetup: func(_ sqlmock.Sqlmock, _ *db.IncidentsParams) {}, - expectedStatus: http.StatusBadRequest, - expectedBody: fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - r, m, _ := initTests(t) - if tc.expectedStatus == http.StatusOK { - params := &db.IncidentsParams{} // Expected params for the mock - tc.mockSetup(m, params) - } - w := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodGet, tc.url, nil) - r.ServeHTTP(w, req) - t.Logf("Test Case: %s - Expected Response: %s", tc.name, tc.expectedBody) - t.Logf("Test Case: %s - Actual Response: %s", tc.name, w.Body.String()) - assert.Equal(t, tc.expectedStatus, w.Code) - assert.JSONEq(t, tc.expectedBody, w.Body.String()) - assert.NoError(t, m.ExpectationsWereMet()) - }) - } -} - func TestReturn404Handler(t *testing.T) { - r, _, _ := initTests(t) + gin.SetMode(gin.TestMode) + r := gin.New() + r.NoRoute(errors.Return404) + w := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/anyendpoint", nil) r.ServeHTTP(w, req) @@ -318,244 +30,6 @@ func TestReturn404Handler(t *testing.T) { assert.JSONEq(t, `{"errMsg":"page not found"}`, w.Body.String()) } -func TestGetEventsHandler(t *testing.T) { - const totalEvents = 60 - const maintenanceCount = 10 - const infoCount = 10 - - r, m, _ := initTests(t) - - mockEvents := make([]*db.Incident, 0, totalEvents) - startTime := time.Now().UTC().Add(-time.Hour * 24 * 30) - - for i := 1; i <= totalEvents; i++ { - eventTitle := fmt.Sprintf("Event %d", i) - eventDescription := fmt.Sprintf("Description for Event %d", i) - eventStartTime := startTime.Add(time.Hour * time.Duration(i)) - eventEndTime := eventStartTime.Add(time.Minute * 5) - componentID := 150 + (i % 5) - var eventType string - var impact int - var status event.Status - var statusText string - - switch { - case i <= maintenanceCount: - eventType = event.TypeMaintenance - impact = 0 - status = event.MaintenancePlanned - statusText = event.MaintenancePlannedStatusText() - case i <= maintenanceCount+infoCount: - eventType = event.TypeInformation - impact = 0 - status = event.InfoPlanned - statusText = event.InfoPlannedStatusText() - default: - eventType = event.TypeIncident - impact = (i % 3) + 1 // Cycle through 1, 2, 3 - status = event.IncidentDetected - statusText = event.IncidentDetectedStatusText() - } - - textPtr := new(string) - *textPtr = eventTitle - descPtr := new(string) - *descPtr = eventDescription - impactPtr := new(int) - *impactPtr = impact - startTimePtr := new(time.Time) - *startTimePtr = eventStartTime - endTimePtr := new(time.Time) - *endTimePtr = eventEndTime - - mockEvent := &db.Incident{ - ID: uint(i), - Text: textPtr, - Description: descPtr, - StartDate: startTimePtr, - EndDate: endTimePtr, - Impact: impactPtr, - Type: eventType, - System: false, - Components: []db.Component{ - {ID: uint(componentID), Name: fmt.Sprintf("Component %d", componentID)}, - }, - Statuses: []db.IncidentStatus{ - {ID: uint(i), IncidentID: uint(i), Status: status, Text: statusText, Timestamp: eventStartTime}, - }, - Status: status, - } - mockEvents = append(mockEvents, mockEvent) - } - - testCases := []struct { - name string - url string - limit int - page int - expectedCount int - expectedPages int - expectedStatus int - }{ - { - name: "Get first page with limit 20", - url: "/v2/events?limit=20&page=1", - limit: 20, - page: 1, - expectedCount: 20, - expectedPages: 3, - expectedStatus: http.StatusOK, - }, - { - name: "Get second page with limit 20", - url: "/v2/events?limit=20&page=2", - limit: 20, - page: 2, - expectedCount: 20, - expectedPages: 3, - expectedStatus: http.StatusOK, - }, - { - name: "Get last page with limit 20", - url: "/v2/events?limit=20&page=3", - limit: 20, - page: 3, - expectedCount: 20, - expectedPages: 3, - expectedStatus: http.StatusOK, - }, - { - name: "Get page beyond total pages", - url: "/v2/events?limit=20&page=4", - limit: 20, - page: 4, - expectedCount: 0, - expectedPages: 3, - expectedStatus: http.StatusOK, - }, - { - name: "Get events with default limit (50)", - url: "/v2/events?page=1", - limit: 50, - page: 1, - expectedCount: 50, - expectedPages: 2, - expectedStatus: http.StatusOK, - }, - { - name: "Get events with invalid limit (150), returns validation error", - url: "/v2/events?limit=150&page=1", - limit: 150, - page: 1, - expectedCount: 0, - expectedPages: 0, - expectedStatus: http.StatusBadRequest, - }, - { - name: "Get page that is out of bounds but should return empty data", - url: "/v2/events?limit=50&page=3", - limit: 50, - page: 3, - expectedCount: 0, - expectedPages: 2, - expectedStatus: http.StatusOK, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - reversedEvents := make([]*db.Incident, totalEvents) - for i := range totalEvents { - reversedEvents[i] = mockEvents[totalEvents-1-i] - } - - start := (tc.page - 1) * tc.limit - end := start + tc.limit - if start > totalEvents { - start = totalEvents - } - if end > totalEvents { - end = totalEvents - } - paginatedMock := reversedEvents[start:end] - - if tc.expectedStatus == http.StatusOK { - prepareMockForEvents(t, m, paginatedMock, totalEvents) - } - - w := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodGet, tc.url, nil) - r.ServeHTTP(w, req) - - t.Logf("Response Body: %s", w.Body.String()) - - assert.Equal(t, tc.expectedStatus, w.Code) - - if tc.name == "Get events with invalid limit (150), returns validation error" { - assert.JSONEq(t, fmt.Sprintf(`{"errMsg":"%s"}`, errors.ErrIncidentFQueryInvalidFormat), w.Body.String()) - } - - assert.Equal(t, tc.expectedStatus, w.Code) - - if tc.expectedStatus == http.StatusOK { - var response struct { - Data []Incident `json:"data"` - Pagination struct { - PageIndex int `json:"pageIndex"` - RecordsPerPage int `json:"recordsPerPage"` - TotalRecords int64 `json:"totalRecords"` - TotalPages int `json:"totalPages"` - } `json:"pagination"` - } - err := json.Unmarshal(w.Body.Bytes(), &response) - require.NoError(t, err) - - assert.Len(t, response.Data, tc.expectedCount) - assert.Equal(t, tc.page, response.Pagination.PageIndex) - assert.Equal(t, tc.limit, response.Pagination.RecordsPerPage) - assert.Equal(t, int64(totalEvents), response.Pagination.TotalRecords) - assert.Equal(t, tc.expectedPages, response.Pagination.TotalPages) - } - - assert.NoError(t, m.ExpectationsWereMet()) - }) - } -} - -func TestGetComponentsAvailabilityHandler(t *testing.T) { - r, m, _ := initTests(t) - // Mocking data for testing - - currentTime := time.Now().UTC() - year, month, _ := currentTime.Date() - - firstDayOfLastMonth := time.Date(year, month-1, 1, 0, 0, 0, 0, time.UTC) - testTime := firstDayOfLastMonth - prepareAvailability(t, m, testTime) - expectedAvailability := "" - - for i := range [12]int{} { - availYear, availMonth := getYearAndMonth(year, int(month), i) - percentage := 100 - // For the second month (current month in test setup), set percentage to 0 - if i == 1 { - percentage = 0 - } - expectedAvailability += fmt.Sprintf(`{"year":%d,"month":%d,"percentage":%d},`, availYear, availMonth, percentage) - } - - // Remove trailing comma - expectedAvailability = expectedAvailability[:len(expectedAvailability)-1] - - response := fmt.Sprintf(`{"data":[{"id":151,"name":"Component B","availability":[%s],"region":"B"}]}`, expectedAvailability) - - w := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodGet, "/v2/availability", nil) - r.ServeHTTP(w, req) - assert.Equal(t, 200, w.Code) - assert.Equal(t, response, w.Body.String()) -} - func TestCalculateAvailability(t *testing.T) { type testCase struct { testDescription string @@ -843,424 +317,3 @@ func TestPatchEventDescriptionTooLongHandler(t *testing.T) { require.Equal(t, http.StatusBadRequest, w.Code) assert.JSONEq(t, `{"errMsg":"event description should be 1500 characters or fewer"}`, w.Body.String()) } - -func TestPatchEventUpdateHandler(t *testing.T) { - startDate := "2025-08-01T11:45:26.371Z" - endDate := "2025-08-04T11:45:26.371Z" - testTime, err := time.Parse(time.RFC3339, startDate) - require.NoError(t, err) - testEndTime, err := time.Parse(time.RFC3339, endDate) - require.NoError(t, err) - - eventID := 111 - impact2 := 2 // Incident - systemTrue := true - updateID1 := 87 - updateID2 := 88 - updateIndex1 := 0 - updateIndex2 := 1 - version1 := 1 - - // Mock data setup - incidentA := db.Incident{ - ID: uint(eventID), - Text: &[]string{"Incident title A"}[0], - Description: &[]string{"Description A"}[0], - StartDate: &testTime, - EndDate: &testEndTime, - Impact: &impact2, - Type: event.TypeIncident, - System: systemTrue, - Version: &version1, - Components: []db.Component{ - { - ID: 151, - Name: "Component A", - Attrs: []db.ComponentAttr{ - {ID: 462, ComponentID: 151, Name: "category", Value: "A"}, - {ID: 463, ComponentID: 151, Name: "region", Value: "A"}, - {ID: 464, ComponentID: 151, Name: "type", Value: "a"}, - }, - }, - }, - Statuses: []db.IncidentStatus{ - {ID: uint(updateID1), IncidentID: 111, Status: "analysing", Text: "Incident analysing.", Timestamp: testTime}, - {ID: uint(updateID2), IncidentID: 111, Status: "resolved", Text: "Incident resolved.", Timestamp: testEndTime}, - }, - } - - responseAfterFirst := fmt.Sprintf( - `{"id":%d,"status":"analysing","text":"Updated: analysing","timestamp":"%s"}`, - updateIndex1, startDate, - ) - responseAfterSecond := fmt.Sprintf( - `{"id":%d,"status":"resolved","text":"Updated: resolved","timestamp":"%s"}`, - updateIndex2, endDate, - ) - - testCases := []struct { - name string - url string - body string - mockSetup func(m sqlmock.Sqlmock) - expectedStatus int - expectedBody string - }{ - // Tests for /v2/incidents endpoint (deprecated) - { - name: "Update incident update id=0 via /v2/incidents", - url: fmt.Sprintf("incidents/111/updates/%d", updateIndex1), - body: `{"text": "Updated: analysing"}`, - mockSetup: func(m sqlmock.Sqlmock) { - prepareMockForPatchEventUpdate( - t, m, &incidentA, - uint(updateID1), - "Updated: analysing", - updateIndex1, - ) - }, - expectedStatus: http.StatusOK, - expectedBody: responseAfterFirst, - }, - { - name: "Update incident update id=1 via /v2/incidents", - url: fmt.Sprintf("incidents/111/updates/%d", updateIndex2), - body: `{"text": "Updated: resolved"}`, - mockSetup: func(m sqlmock.Sqlmock) { - prepareMockForPatchEventUpdate( - t, m, &incidentA, - uint(updateID2), - "Updated: resolved", - updateIndex2, - ) - }, - expectedStatus: http.StatusOK, - expectedBody: responseAfterSecond, - }, - // Tests for /v2/events endpoint (new) - { - name: "Update event update id=0 via /v2/events", - url: fmt.Sprintf("events/111/updates/%d", updateIndex1), - body: `{"text": "Updated: analysing"}`, - mockSetup: func(m sqlmock.Sqlmock) { - prepareMockForPatchEventUpdate( - t, m, &incidentA, - uint(updateID1), - "Updated: analysing", - updateIndex1, - ) - }, - expectedStatus: http.StatusOK, - expectedBody: responseAfterFirst, - }, - { - name: "Update event update id=1 via /v2/events", - url: fmt.Sprintf("events/111/updates/%d", updateIndex2), - body: `{"text": "Updated: resolved"}`, - mockSetup: func(m sqlmock.Sqlmock) { - prepareMockForPatchEventUpdate( - t, m, &incidentA, - uint(updateID2), - "Updated: resolved", - updateIndex2, - ) - }, - expectedStatus: http.StatusOK, - expectedBody: responseAfterSecond, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - r, m, _ := initTests(t) - tc.mockSetup(m) - - w := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodPatch, fmt.Sprintf("/v2/%s", tc.url), strings.NewReader(tc.body)) - req.Header.Set("Content-Type", "application/json") - - r.ServeHTTP(w, req) - - t.Logf("Test Case: %s - Expected Response: %s", tc.name, tc.expectedBody) - t.Logf("Test Case: %s - Actual Response: %s", tc.name, w.Body.String()) - - assert.Equal(t, tc.expectedStatus, w.Code) - assert.JSONEq(t, tc.expectedBody, w.Body.String()) - assert.NoError(t, m.ExpectationsWereMet()) - }) - } -} - -// TestPatchIncidentVersionConflict tests the optimistic locking mechanism for maintenance event updates. -// This test verifies that when a PATCH request is sent with an outdated version number, -// the API correctly returns HTTP 409 Conflict. -// -// Scenario: -// - Maintenance event in database has version = 2 -// - PATCH request sent with version = 1 (outdated) -// - UPDATE query returns 0 affected rows (no match because version doesn't match) -// - API returns HTTP 409 Conflict with "version conflict" message. -func TestPatchIncidentVersionConflict(t *testing.T) { - startDate := "2025-08-01T11:45:26.371Z" - updateDate := "2025-08-02T11:45:26.371Z" - testTime, err := time.Parse(time.RFC3339, startDate) - require.NoError(t, err) - - eventID := 222 - impact0 := 0 // Maintenance - systemFalse := false - versionInDB := 2 // Version in database - versionInRequest := 1 // Version in PATCH request (outdated) - - // Mock data setup - maintenance in DB has version 2 with planned status - maintenanceInDB := db.Incident{ - ID: uint(eventID), - Text: &[]string{"Maintenance title"}[0], - Description: &[]string{"Description"}[0], - StartDate: &testTime, - EndDate: nil, - Impact: &impact0, - Type: event.TypeMaintenance, - System: systemFalse, - Version: &versionInDB, - Components: []db.Component{ - { - ID: 151, - Name: "Component A", - Attrs: []db.ComponentAttr{ - {ID: 462, ComponentID: 151, Name: "category", Value: "A"}, - {ID: 463, ComponentID: 151, Name: "region", Value: "A"}, - {ID: 464, ComponentID: 151, Name: "type", Value: "a"}, - }, - }, - }, - Statuses: []db.IncidentStatus{ - {ID: 91, IncidentID: uint(eventID), Status: event.MaintenancePlanned, Text: "Maintenance planned.", Timestamp: testTime}, - }, - } - - r, m, _ := initTests(t) - - // Mock GetIncident for EventExistenceCheck middleware - rowsInc, incidentIDs, componentIDs := prepareIncidentRows([]*db.Incident{&maintenanceInDB}) - m.ExpectQuery(`^SELECT (.+) FROM "incident"`).WillReturnRows(rowsInc) - - rowsIncComp, rowsComp, rowsCompAttr, rowsStatus := prepareRelatedRows([]*db.Incident{&maintenanceInDB}) - m.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`). - WithArgs(incidentIDs...). - WillReturnRows(rowsIncComp) - m.ExpectQuery(`^SELECT (.+) FROM "component"`). - WithArgs(componentIDs...). - WillReturnRows(rowsComp) - m.ExpectQuery("^SELECT (.+) FROM \"component_attribute\""). - WillReturnRows(rowsCompAttr) - m.ExpectQuery(`^SELECT (.+) FROM "incident_status"`). - WithArgs(incidentIDs...). - WillReturnRows(rowsStatus) - - // Mock the UPDATE query that will return 0 rows affected (version mismatch) - // The UPDATE uses WHERE id = ? AND version = ?, so with version=1 it won't match (DB has version=2) - m.ExpectBegin() - m.ExpectExec(`^UPDATE "incident" SET .+ WHERE id = \$\d+ AND version = \$\d+$`). - WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), - sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), - eventID, versionInRequest). - WillReturnResult(sqlmock.NewResult(0, 0)) // 0 rows affected - version conflict! - m.ExpectRollback() - - // Prepare PATCH request with version 1 (but DB has version 2) - requestBody := fmt.Sprintf(`{ - "message": "Maintenance update", - "status": "in_progress", - "update_date": "%s", - "version": %d - }`, updateDate, versionInRequest) - - w := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodPatch, fmt.Sprintf("/v2/events/%d", eventID), strings.NewReader(requestBody)) - req.Header.Set("Content-Type", "application/json") - - r.ServeHTTP(w, req) - - t.Logf("Response: %s", w.Body.String()) - - // Assert that we get 409 Conflict with "version conflict" message - assert.Equal(t, http.StatusConflict, w.Code, "Expected HTTP 409 Conflict for version mismatch") - assert.Contains(t, w.Body.String(), "version conflict", "Response should contain 'version conflict' message") - assert.NoError(t, m.ExpectationsWereMet()) -} - -// TestPatchIncidentVersionConflictIgnoredForNonMaintenance tests that version conflict -// does NOT block updates for incident and info types (version check is only enforced for maintenance). -func TestPatchIncidentVersionConflictIgnoredForNonMaintenance(t *testing.T) { - testCases := []struct { - name string - eventType string - impact int - status event.Status - patchStatus string - }{ - { - name: "incident type ignores version conflict", - eventType: event.TypeIncident, - impact: 2, - status: event.IncidentAnalysing, - patchStatus: "fixing", - }, - { - name: "info type ignores version conflict", - eventType: event.TypeInformation, - impact: 0, - status: event.InfoPlanned, - patchStatus: "active", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - startDate := "2025-08-01T11:45:26.371Z" - updateDate := "2025-08-02T11:45:26.371Z" - testTime, err := time.Parse(time.RFC3339, startDate) - require.NoError(t, err) - - eventID := 223 - systemFalse := false - versionInDB := 2 - versionInRequest := 1 // Outdated version - - eventInDB := db.Incident{ - ID: uint(eventID), - Text: &[]string{"Event title"}[0], - Description: &[]string{"Description"}[0], - StartDate: &testTime, - EndDate: nil, - Impact: &tc.impact, - Type: tc.eventType, - System: systemFalse, - Version: &versionInDB, - Components: []db.Component{ - { - ID: 151, - Name: "Component A", - Attrs: []db.ComponentAttr{ - {ID: 462, ComponentID: 151, Name: "category", Value: "A"}, - {ID: 463, ComponentID: 151, Name: "region", Value: "A"}, - {ID: 464, ComponentID: 151, Name: "type", Value: "a"}, - }, - }, - }, - Statuses: []db.IncidentStatus{ - {ID: 91, IncidentID: uint(eventID), Status: tc.status, Text: "Status.", Timestamp: testTime}, - }, - } - - r, m, _ := initTests(t) - - // Mock for EventExistenceCheck middleware - rowsInc, incidentIDs, componentIDs := prepareIncidentRows([]*db.Incident{&eventInDB}) - m.ExpectQuery(`^SELECT (.+) FROM "incident"`).WillReturnRows(rowsInc) - - rowsIncComp, rowsComp, rowsCompAttr, rowsStatus := prepareRelatedRows([]*db.Incident{&eventInDB}) - m.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`). - WithArgs(incidentIDs...). - WillReturnRows(rowsIncComp) - m.ExpectQuery(`^SELECT (.+) FROM "component"`). - WithArgs(componentIDs...). - WillReturnRows(rowsComp) - m.ExpectQuery("^SELECT (.+) FROM \"component_attribute\""). - WillReturnRows(rowsCompAttr) - m.ExpectQuery(`^SELECT (.+) FROM "incident_status"`). - WithArgs(incidentIDs...). - WillReturnRows(rowsStatus) - - // For non-maintenance, UPDATE does NOT include version in WHERE clause - m.ExpectBegin() - m.ExpectExec(`^UPDATE "incident" SET .+ WHERE id = \$\d+$`). - WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), - sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), - eventID). - WillReturnResult(sqlmock.NewResult(0, 1)) - m.ExpectQuery(`^INSERT INTO "incident_status"`). - WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(92)) - m.ExpectCommit() - - // Mock for GetIncident after update (reload) - rowsInc2, incidentIDs2, componentIDs2 := prepareIncidentRows([]*db.Incident{&eventInDB}) - m.ExpectQuery(`^SELECT (.+) FROM "incident"`).WillReturnRows(rowsInc2) - - rowsIncComp2, rowsComp2, rowsCompAttr2, rowsStatus2 := prepareRelatedRows([]*db.Incident{&eventInDB}) - m.ExpectQuery(`^SELECT (.+) FROM "incident_component_relation"`). - WithArgs(incidentIDs2...). - WillReturnRows(rowsIncComp2) - m.ExpectQuery(`^SELECT (.+) FROM "component"`). - WithArgs(componentIDs2...). - WillReturnRows(rowsComp2) - m.ExpectQuery("^SELECT (.+) FROM \"component_attribute\""). - WillReturnRows(rowsCompAttr2) - m.ExpectQuery(`^SELECT (.+) FROM "incident_status"`). - WithArgs(incidentIDs2...). - WillReturnRows(rowsStatus2) - - requestBody := fmt.Sprintf(`{ - "message": "Event update", - "status": "%s", - "update_date": "%s", - "version": %d - }`, tc.patchStatus, updateDate, versionInRequest) - - w := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodPatch, fmt.Sprintf("/v2/events/%d", eventID), strings.NewReader(requestBody)) - req.Header.Set("Content-Type", "application/json") - - r.ServeHTTP(w, req) - - t.Logf("Response: %s", w.Body.String()) - - assert.Equal(t, http.StatusOK, w.Code, "Expected HTTP 200 OK - version conflict should be ignored for non-maintenance") - assert.NoError(t, m.ExpectationsWereMet()) - }) - } -} - -func TestModifyEventUpdate(t *testing.T) { - _, m, d := initTests(t) - startDate := "2025-08-01T11:45:26.371Z" - testTime, err := time.Parse(time.RFC3339, startDate) - require.NoError(t, err) - - createdAt := testTime - modifiedAt := time.Now().UTC() - - eventID := 111 - updateID := 87 - updatedText := "Updated: analysing" - - status := db.IncidentStatus{ - ID: uint(updateID), - IncidentID: uint(eventID), - Status: "analysing", - Text: "Incident analysing.", - Timestamp: testTime, - CreatedAt: &createdAt, - ModifiedAt: &createdAt, - } - prepareMockForModifyEventUpdate(t, m, status, updatedText, modifiedAt) - - returningRows := sqlmock.NewRows([]string{"id", "incident_id", "text", "status", "timestamp", "created_at", "modified_at"}). - AddRow(status.ID, status.IncidentID, updatedText, status.Status, status.Timestamp, createdAt, modifiedAt) - m.ExpectQuery(`^SELECT \* FROM "incident_status" WHERE id = \$1 AND incident_id = \$2`). - WithArgs(status.ID, status.IncidentID). - WillReturnRows(returningRows) - - status.Text = updatedText - - updated, err := d.ModifyEventUpdate(status) - require.NoError(t, err) - require.NotZero(t, updated.ID) - require.Equal(t, updatedText, updated.Text) - require.NotNil(t, updated.CreatedAt) - require.NotNil(t, updated.ModifiedAt) - require.Equal(t, createdAt, *updated.CreatedAt) - require.Equal(t, modifiedAt.Truncate(time.Microsecond), updated.ModifiedAt.Truncate(time.Microsecond)) - require.True(t, updated.ModifiedAt.After(*updated.CreatedAt) || updated.ModifiedAt.Equal(*updated.CreatedAt)) -} diff --git a/internal/db/mock.go b/internal/db/mock.go deleted file mode 100644 index 32c8cba..0000000 --- a/internal/db/mock.go +++ /dev/null @@ -1,19 +0,0 @@ -package db - -import ( - "entgo.io/ent/dialect" - entsql "entgo.io/ent/dialect/sql" - "github.com/DATA-DOG/go-sqlmock" - - "github.com/stackmon/otc-status-dashboard/ent" -) - -func NewWithMock() (*DB, sqlmock.Sqlmock, error) { - mockDB, mock, err := sqlmock.New() - if err != nil { - return nil, nil, err - } - - e := ent.NewClient(ent.Driver(entsql.OpenDB(dialect.Postgres, mockDB))) - return &DB{sql: mockDB, e: e}, mock, nil -} diff --git a/internal/db/notification_ops.go b/internal/db/notification_ops.go index dfb3d62..eab7309 100644 --- a/internal/db/notification_ops.go +++ b/internal/db/notification_ops.go @@ -56,11 +56,20 @@ FROM notification_outbox` // Rows stuck in pending with a rising attempt count are the usual symptom of a // misconfigured relay, so every status must be reachable, not just failed. func (db *DB) ListNotificationsByStatus(ctx context.Context, status string, limit int) ([]NotificationOutbox, error) { - rows, err := db.e.NotificationOutbox.Query(). + // Ent drops Limit(0) while SQL LIMIT 0 selects nothing; keep the SQL semantics + // so a zero limit returns no rows and a negative one means "no limit". + if limit == 0 { + return []NotificationOutbox{}, nil + } + + query := db.e.NotificationOutbox.Query(). Where(notificationoutbox.StatusEQ(status)). - Order(notificationoutbox.ByUpdatedAt(entsql.OrderDesc())). - Limit(limit). - All(ctx) + Order(notificationoutbox.ByUpdatedAt(entsql.OrderDesc())) + if limit > 0 { + query = query.Limit(limit) + } + + rows, err := query.All(ctx) if err != nil { return nil, err } diff --git a/internal/db/notification_test.go b/internal/db/notification_test.go index 9e6ddf6..7033d7d 100644 --- a/internal/db/notification_test.go +++ b/internal/db/notification_test.go @@ -3,4 +3,4 @@ package db // Storage-layer behavior for notification_outbox (Enqueue, ClaimPending, // MarkSent, MarkFailed, RecoverStaleProcessing) is verified against a real // Postgres container in tests/notifications_test.go, because FOR UPDATE SKIP -// LOCKED and transactional lease semantics cannot be exercised with sqlmock. +// LOCKED and transactional lease semantics need a real database. diff --git a/tests/checker_notifications_test.go b/tests/checker_notifications_test.go index 689534f..6c5a62d 100644 --- a/tests/checker_notifications_test.go +++ b/tests/checker_notifications_test.go @@ -6,8 +6,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" - gormpostgres "gorm.io/driver/postgres" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/checker" "github.com/stackmon/otc-status-dashboard/internal/conf" @@ -37,12 +35,7 @@ func TestChecker_ReviewedToPlanned_EnqueuesStatusChangedToCreator(t *testing.T) eventID := resp.Result[0].IncidentID transitionTo(t, r, eventID, event.MaintenanceReviewed, adminToken) // -> reviewed - g, err := gorm.Open(gormpostgres.New(gormpostgres.Config{DSN: databaseURL}), &gorm.Config{}) - require.NoError(t, err) - sqlDB, err := g.DB() - require.NoError(t, err) - sqlDB.SetMaxOpenConns(2) - t.Cleanup(func() { _ = sqlDB.Close() }) + g := openRawDB(t) // No outbox rows yet (publisher was off during API calls). require.Equal(t, int64(0), outboxCount(t, g, eventID)) @@ -53,8 +46,7 @@ func TestChecker_ReviewedToPlanned_EnqueuesStatusChangedToCreator(t *testing.T) require.NoError(t, chk.CheckMaintenance()) // reviewed -> planned - var rows []db.NotificationOutbox - require.NoError(t, g.Where("incident_id = ?", eventID).Find(&rows).Error) + rows := queryOutbox(t, g, "incident_id = $1", eventID) require.Len(t, rows, 1, "one notification per real transition") assert.Equal(t, db.NotificationKindStatusChanged, rows[0].Kind) assert.Equal(t, "test@example.com", rows[0].Recipient, "planned notifies creator only") @@ -68,12 +60,7 @@ func TestChecker_NoTransition_EnqueuesNothing(t *testing.T) { resp := createEventOK(t, r, maintenanceData(), adminToken) // admin -> planned (future start) eventID := resp.Result[0].IncidentID - g, err := gorm.Open(gormpostgres.New(gormpostgres.Config{DSN: databaseURL}), &gorm.Config{}) - require.NoError(t, err) - sqlDB, err := g.DB() - require.NoError(t, err) - sqlDB.SetMaxOpenConns(2) - t.Cleanup(func() { _ = sqlDB.Close() }) + g := openRawDB(t) chk, err := checker.New(notifCheckerConfig(), zap.NewNop()) require.NoError(t, err) diff --git a/tests/db_tx_test.go b/tests/db_tx_test.go index fcc2913..a39c957 100644 --- a/tests/db_tx_test.go +++ b/tests/db_tx_test.go @@ -28,9 +28,8 @@ func TestWithTx_CommitsIncidentAndOutboxAtomically(t *testing.T) { }) require.NoError(t, err) - var incCount, outCount int64 - require.NoError(t, g.Model(&db.Incident{}).Where("id = ?", incID).Count(&incCount).Error) - require.NoError(t, g.Model(&db.NotificationOutbox{}).Where("incident_id = ?", incID).Count(&outCount).Error) + incCount := tableCount(t, g, "incident", "id = $1", incID) + outCount := tableCount(t, g, "notification_outbox", "incident_id = $1", incID) assert.Equal(t, int64(1), incCount) assert.Equal(t, int64(1), outCount) } @@ -57,9 +56,8 @@ func TestWithTx_RollsBackBothOnError(t *testing.T) { }) require.ErrorIs(t, err, sentinel) - var incCount, outCount int64 - require.NoError(t, g.Model(&db.Incident{}).Where("id = ?", incID).Count(&incCount).Error) - require.NoError(t, g.Model(&db.NotificationOutbox{}).Where("dedup_key = ?", dedup).Count(&outCount).Error) + incCount := tableCount(t, g, "incident", "id = $1", incID) + outCount := tableCount(t, g, "notification_outbox", "dedup_key = $1", dedup) assert.Equal(t, int64(0), incCount, "incident rolled back") assert.Equal(t, int64(0), outCount, "no orphan email task") } @@ -86,8 +84,7 @@ func TestModifyIncidentTx_SharedTxWithEnqueue(t *testing.T) { require.NoError(t, err) assert.Equal(t, event.MaintenanceReviewed, got.Status) - var outCount int64 - require.NoError(t, g.Model(&db.NotificationOutbox{}).Where("dedup_key = ?", row.DedupKey).Count(&outCount).Error) + outCount := tableCount(t, g, "notification_outbox", "dedup_key = $1", row.DedupKey) assert.Equal(t, int64(1), outCount) } @@ -96,13 +93,12 @@ func TestModifyEventUpdateTx_UpdatesText(t *testing.T) { incID := seedIncident(t, d) // Seed one status row for the incident. - status := db.IncidentStatus{IncidentID: incID, Status: event.MaintenancePendingReview, Text: "original"} - require.NoError(t, g.Create(&status).Error) + statusID := insertIncidentStatus(t, g, incID, string(event.MaintenancePendingReview), "original") var updated db.IncidentStatus err := d.WithTx(context.Background(), func(tx *db.Tx) error { u, e := d.ModifyEventUpdateTx(tx, db.IncidentStatus{ - ID: status.ID, IncidentID: incID, Text: "patched", + ID: statusID, IncidentID: incID, Text: "patched", }) if e != nil { return e diff --git a/tests/main_test.go b/tests/main_test.go index fdebfef..4482cc0 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -20,8 +20,6 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/require" "go.uber.org/zap" - gormpostgres "gorm.io/driver/postgres" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/api" "github.com/stackmon/otc-status-dashboard/internal/api/auth" @@ -136,12 +134,9 @@ func initTests(t *testing.T) *gin.Engine { t.Helper() t.Log("init structs") - d, err := db.New(&conf.Config{ - DB: databaseURL, - // if you want to debug gorm, uncomment it - //LogLevel: conf.DevelopMode, - }) + d, err := db.New(&conf.Config{DB: databaseURL}) require.NoError(t, err) + t.Cleanup(func() { _ = d.Close() }) gin.SetMode(gin.TestMode) r := gin.Default() @@ -245,14 +240,7 @@ func truncateIncidents(t *testing.T) { t.Helper() t.Log("cleaning up incident-related tables before test") - gormDB, err := gorm.Open(gormpostgres.Open(databaseURL), &gorm.Config{}) - require.NoError(t, err, "failed to open gorm connection for truncation") - - result := gormDB.Exec("TRUNCATE TABLE incident, incident_status, incident_component_relation, notification_outbox RESTART IDENTITY") - require.NoError(t, result.Error, "failed to truncate incident tables") - - sqlDB, err := gormDB.DB() - require.NoError(t, err, "failed to get sql.DB from gorm for closing") - err = sqlDB.Close() - require.NoError(t, err, "failed to close gorm connection for truncation") + sqlDB := openRawDB(t) + _, err := sqlDB.Exec("TRUNCATE TABLE incident, incident_status, incident_component_relation, notification_outbox RESTART IDENTITY") + require.NoError(t, err, "failed to truncate incident tables") } diff --git a/tests/notification_worker_test.go b/tests/notification_worker_test.go index 438262b..2c2d6e0 100644 --- a/tests/notification_worker_test.go +++ b/tests/notification_worker_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/db" "github.com/stackmon/otc-status-dashboard/internal/notification" @@ -63,13 +62,6 @@ func testWorker(t *testing.T, d *db.DB, sender notification.Sender, maxAttempts return w } -func fetchByDedup(t *testing.T, g *gorm.DB, dedup string) db.NotificationOutbox { - t.Helper() - var row db.NotificationOutbox - require.NoError(t, g.Where("dedup_key = ?", dedup).First(&row).Error) - return row -} - func TestWorker_DeliversAllPending(t *testing.T) { truncateIncidents(t) ctx := context.Background() @@ -86,11 +78,7 @@ func TestWorker_DeliversAllPending(t *testing.T) { assert.ElementsMatch(t, recipients, fake.recipients()) - var notSent int64 - require.NoError(t, g.Model(&db.NotificationOutbox{}). - Where("incident_id = ? AND status <> ?", incID, db.NotificationStatusSent). - Count(¬Sent).Error) - assert.Equal(t, int64(0), notSent, "all rows delivered") + assert.Equal(t, int64(0), outboxNotSentCount(t, g, int(incID)), "all rows delivered") } func TestWorker_FailedSendRetriesWithBackoff(t *testing.T) { diff --git a/tests/notifications_api_test.go b/tests/notifications_api_test.go index 5d80234..af56448 100644 --- a/tests/notifications_api_test.go +++ b/tests/notifications_api_test.go @@ -1,6 +1,7 @@ package tests import ( + "database/sql" "net/http" "testing" @@ -8,8 +9,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" - gormpostgres "gorm.io/driver/postgres" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/api" apiErrors "github.com/stackmon/otc-status-dashboard/internal/api/errors" @@ -21,22 +20,15 @@ import ( ) // initNotifRouter builds a maintenance router with a real, enabled notification -// publisher wired into the create/patch handlers, plus a raw gorm handle to verify +// publisher wired into the create/patch handlers, plus a raw handle to verify // the outbox. -func initNotifRouter(t *testing.T) (*gin.Engine, *gorm.DB) { +func initNotifRouter(t *testing.T) (*gin.Engine, *sql.DB) { t.Helper() d, err := db.New(&conf.Config{DB: databaseURL}) require.NoError(t, err) t.Cleanup(func() { _ = d.Close() }) - g, err := gorm.Open(gormpostgres.New(gormpostgres.Config{DSN: databaseURL}), &gorm.Config{}) - require.NoError(t, err) - sqlDB, err := g.DB() - require.NoError(t, err) - sqlDB.SetMaxOpenConns(2) - t.Cleanup(func() { _ = sqlDB.Close() }) - pub := notification.NewPublisher(notification.Config{ Enabled: true, ReviewSMOD: "smod@com.com", @@ -70,25 +62,7 @@ func initNotifRouter(t *testing.T) (*gin.Engine, *gorm.DB) { api.CheckEventExistenceMW(d, logger), v2.PatchIncidentHandler(d, logger, pub)) - return r, g -} - -func outboxRecipients(t *testing.T, g *gorm.DB, incidentID int) []string { - t.Helper() - var rows []db.NotificationOutbox - require.NoError(t, g.Where("incident_id = ?", incidentID).Find(&rows).Error) - out := make([]string, 0, len(rows)) - for i := range rows { - out = append(out, rows[i].Recipient) - } - return out -} - -func outboxCount(t *testing.T, g *gorm.DB, incidentID int) int64 { - t.Helper() - var n int64 - require.NoError(t, g.Model(&db.NotificationOutbox{}).Where("incident_id = ?", incidentID).Count(&n).Error) - return n + return r, openRawDB(t) } func TestAPI_CreatorCreateMaintenance_EnqueuesReviewAudienceAndCreator(t *testing.T) { diff --git a/tests/notifications_e2e_test.go b/tests/notifications_e2e_test.go index 2ea5bfb..e50f50a 100644 --- a/tests/notifications_e2e_test.go +++ b/tests/notifications_e2e_test.go @@ -6,23 +6,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/db" "github.com/stackmon/otc-status-dashboard/internal/event" ) -func outboxRecipientsByKind(t *testing.T, g *gorm.DB, incidentID int, kind string) []string { - t.Helper() - var rows []db.NotificationOutbox - require.NoError(t, g.Where("incident_id = ? AND kind = ?", incidentID, kind).Find(&rows).Error) - out := make([]string, 0, len(rows)) - for i := range rows { - out = append(out, rows[i].Recipient) - } - return out -} - // TestE2E_CreateMaintenanceDeliversToAllRecipients ties the whole pipeline together: // API create -> outbox rows -> worker drain -> sender delivers each recipient. func TestE2E_CreateMaintenanceDeliversToAllRecipients(t *testing.T) { @@ -42,11 +30,7 @@ func TestE2E_CreateMaintenanceDeliversToAllRecipients(t *testing.T) { []string{"smod@com.com", "ops@com.com", "admin@com.com", "test@example.com"}, fake.recipients()) - var notSent int64 - require.NoError(t, g.Model(&db.NotificationOutbox{}). - Where("incident_id = ? AND status <> ?", eventID, db.NotificationStatusSent). - Count(¬Sent).Error) - assert.Equal(t, int64(0), notSent, "every recipient delivered") + assert.Equal(t, int64(0), outboxNotSentCount(t, g, eventID), "every recipient delivered") } // TestE2E_ReviewedTransitionNotifiesReviewAudience covers the `reviewed` kind row set. @@ -73,8 +57,7 @@ func TestE2E_LifecycleTransitionNotifiesCreatorOnly(t *testing.T) { eventID := resp.Result[0].IncidentID transitionTo(t, r, eventID, event.MaintenanceCancelled, adminToken) // planned -> cancelled - var rows []db.NotificationOutbox - require.NoError(t, g.Where("incident_id = ?", eventID).Find(&rows).Error) + rows := queryOutbox(t, g, "incident_id = $1", eventID) require.NotEmpty(t, rows) for i := range rows { assert.Equal(t, db.NotificationKindStatusChanged, rows[i].Kind) diff --git a/tests/notifications_ops_test.go b/tests/notifications_ops_test.go index b4beeb4..121a21a 100644 --- a/tests/notifications_ops_test.go +++ b/tests/notifications_ops_test.go @@ -3,6 +3,7 @@ package tests import ( "bytes" "context" + "database/sql" "encoding/json" "net/http" "net/http/httptest" @@ -13,8 +14,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" - gormpostgres "gorm.io/driver/postgres" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/api" apiErrors "github.com/stackmon/otc-status-dashboard/internal/api/errors" @@ -23,14 +22,7 @@ import ( "github.com/stackmon/otc-status-dashboard/internal/db" ) -// setOutbox mutates an outbox row by dedup key without touching updated_at -// (UpdateColumns skips autoUpdateTime), so tests can craft ages and states. -func setOutbox(t *testing.T, g *gorm.DB, dedup string, cols map[string]any) { - t.Helper() - require.NoError(t, g.Model(&db.NotificationOutbox{}).Where("dedup_key = ?", dedup).UpdateColumns(cols).Error) -} - -func enqueueWithState(t *testing.T, d *db.DB, g *gorm.DB, incID uint, recipient string, cols map[string]any) string { +func enqueueWithState(t *testing.T, d *db.DB, g *sql.DB, incID uint, recipient string, cols map[string]any) string { t.Helper() row := newOutboxRow(incID, recipient) require.NoError(t, d.Enqueue(context.Background(), nil, row)) @@ -106,8 +98,7 @@ func TestRedriveFailed_AllAndByID(t *testing.T) { b := enqueueWithState(t, d, g, incID, "b@com.com", failedCols) // Re-drive only row a. - var rowA db.NotificationOutbox - require.NoError(t, g.Where("dedup_key = ?", a).First(&rowA).Error) + rowA := fetchByDedup(t, g, a) n, err := d.RedriveFailed(ctx, rowA.ID) require.NoError(t, err) assert.Equal(t, int64(1), n) @@ -143,26 +134,19 @@ func TestDeleteSentBefore(t *testing.T) { require.NoError(t, err) assert.Equal(t, int64(1), deleted, "only the old sent row is pruned") - var remaining int64 - require.NoError(t, g.Model(&db.NotificationOutbox{}).Where("incident_id = ?", incID).Count(&remaining).Error) - assert.Equal(t, int64(2), remaining, "recent sent + failed kept") + assert.Equal(t, int64(2), outboxCount(t, g, int(incID)), "recent sent + failed kept") } // --- API endpoints --- -func initNotifOpsRouter(t *testing.T) (*gin.Engine, *db.DB, *gorm.DB) { +func initNotifOpsRouter(t *testing.T) (*gin.Engine, *db.DB, *sql.DB) { t.Helper() d, err := db.New(&conf.Config{DB: databaseURL}) require.NoError(t, err) t.Cleanup(func() { _ = d.Close() }) - g, err := gorm.Open(gormpostgres.New(gormpostgres.Config{DSN: databaseURL}), &gorm.Config{}) - require.NoError(t, err) - sqlDB, err := g.DB() - require.NoError(t, err) - sqlDB.SetMaxOpenConns(2) - t.Cleanup(func() { _ = sqlDB.Close() }) + g := openRawDB(t) gin.SetMode(gin.TestMode) r := gin.Default() @@ -304,7 +288,7 @@ func TestAPI_RedriveNotifications_EmptyBodyRedrivesAll(t *testing.T) { b := enqueueWithState(t, d, g, incID, "b@com.com", failedCols) w := httptest.NewRecorder() - req, _ := http.NewRequest(http.MethodPost, "/v2/notifications/redrive", nil) + req, _ := http.NewRequest(http.MethodPost, "/v2/notifications/redrive", http.NoBody) req.Header.Set("Authorization", "Bearer "+adminToken) r.ServeHTTP(w, req) diff --git a/tests/notifications_test.go b/tests/notifications_test.go index d1b3310..4f1fb2c 100644 --- a/tests/notifications_test.go +++ b/tests/notifications_test.go @@ -2,6 +2,7 @@ package tests import ( "context" + "database/sql" "fmt" "testing" "time" @@ -9,30 +10,21 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - gormpostgres "gorm.io/driver/postgres" - "gorm.io/gorm" "github.com/stackmon/otc-status-dashboard/internal/conf" "github.com/stackmon/otc-status-dashboard/internal/db" ) -// newNotifDB returns the DB under test plus a raw gorm handle for seeding and -// verification against the real Postgres container. -func newNotifDB(t *testing.T) (*db.DB, *gorm.DB) { +// newNotifDB returns the DB under test plus a raw handle for seeding and +// verification against the real Postgres database. +func newNotifDB(t *testing.T) (*db.DB, *sql.DB) { t.Helper() d, err := db.New(&conf.Config{DB: databaseURL}) require.NoError(t, err) t.Cleanup(func() { _ = d.Close() }) - g, err := gorm.Open(gormpostgres.New(gormpostgres.Config{DSN: databaseURL}), &gorm.Config{}) - require.NoError(t, err) - sqlDB, err := g.DB() - require.NoError(t, err) - sqlDB.SetMaxOpenConns(2) - t.Cleanup(func() { _ = sqlDB.Close() }) - - return d, g + return d, openRawDB(t) } // seedIncident inserts a minimal maintenance incident to satisfy the outbox FK @@ -68,13 +60,6 @@ func newOutboxRow(incidentID uint, recipient string) db.NotificationOutbox { } } -func fetchRow(t *testing.T, g *gorm.DB, id uint) db.NotificationOutbox { - t.Helper() - var row db.NotificationOutbox - require.NoError(t, g.First(&row, id).Error) - return row -} - func TestEnqueue_Success(t *testing.T) { ctx := context.Background() d, g := newNotifDB(t) @@ -83,8 +68,7 @@ func TestEnqueue_Success(t *testing.T) { row := newOutboxRow(incID, "creator@com.com") require.NoError(t, d.Enqueue(ctx, nil, row)) - var stored db.NotificationOutbox - require.NoError(t, g.Where("dedup_key = ?", row.DedupKey).First(&stored).Error) + stored := fetchByDedup(t, g, row.DedupKey) assert.Equal(t, db.NotificationStatusPending, stored.Status) assert.Equal(t, incID, stored.IncidentID) assert.Equal(t, 0, stored.Attempts) @@ -251,8 +235,7 @@ func TestRecoverStaleProcessing_ReturnsToPending(t *testing.T) { // Simulate a crashed pod: push locked_at far into the past. stale := time.Now().UTC().Add(-10 * time.Minute) - require.NoError(t, g.Model(&db.NotificationOutbox{}).Where("id = ?", id). - Update("locked_at", stale).Error) + updateOutbox(t, g, map[string]any{"locked_at": stale}, "id", id) recovered, err := d.RecoverStaleProcessing(ctx, nil, time.Minute, 5) require.NoError(t, err) @@ -277,8 +260,7 @@ func TestRecoverStaleProcessing_FinalWhenAttemptsExhausted(t *testing.T) { id := findClaimedID(t, claimed, row.DedupKey) // attempts is now 1 stale := time.Now().UTC().Add(-10 * time.Minute) - require.NoError(t, g.Model(&db.NotificationOutbox{}).Where("id = ?", id). - Update("locked_at", stale).Error) + updateOutbox(t, g, map[string]any{"locked_at": stale}, "id", id) // maxAttempts=1 with attempts=1 -> recovery marks it failed. recovered, err := d.RecoverStaleProcessing(ctx, nil, time.Minute, 1) diff --git a/tests/rawdb_test.go b/tests/rawdb_test.go new file mode 100644 index 0000000..02bcd52 --- /dev/null +++ b/tests/rawdb_test.go @@ -0,0 +1,191 @@ +package tests + +import ( + "database/sql" + "encoding/json" + "fmt" + "sort" + "strings" + "testing" + + _ "github.com/jackc/pgx/v5/stdlib" + "github.com/stretchr/testify/require" + + "github.com/stackmon/otc-status-dashboard/internal/db" +) + +// openRawDB opens a raw database/sql handle on the test database for seeding and +// verification that the facade does not expose. +func openRawDB(t *testing.T) *sql.DB { + t.Helper() + + sqlDB, err := sql.Open("pgx", databaseURL) + require.NoError(t, err) + sqlDB.SetMaxOpenConns(2) + t.Cleanup(func() { _ = sqlDB.Close() }) + + return sqlDB +} + +const outboxColumns = "id, kind, incident_id, recipient, payload, change_id, dedup_key, " + + "status, attempts, next_attempt_at, locked_by, locked_at, last_error, created_at, updated_at" + +func scanOutboxRows(t *testing.T, rows *sql.Rows) []db.NotificationOutbox { + t.Helper() + defer rows.Close() + + var out []db.NotificationOutbox + for rows.Next() { + var ( + row db.NotificationOutbox + payload []byte + nextAttempt sql.NullTime + lockedBy sql.NullString + lockedAt sql.NullTime + lastError sql.NullString + ) + require.NoError(t, rows.Scan( + &row.ID, &row.Kind, &row.IncidentID, &row.Recipient, &payload, &row.ChangeID, + &row.DedupKey, &row.Status, &row.Attempts, &nextAttempt, &lockedBy, &lockedAt, + &lastError, &row.CreatedAt, &row.UpdatedAt, + )) + if payload != nil { + require.NoError(t, json.Unmarshal(payload, &row.Payload)) + } + if nextAttempt.Valid { + row.NextAttemptAt = &nextAttempt.Time + } + if lockedBy.Valid { + row.LockedBy = &lockedBy.String + } + if lockedAt.Valid { + row.LockedAt = &lockedAt.Time + } + if lastError.Valid { + row.LastError = &lastError.String + } + out = append(out, row) + } + require.NoError(t, rows.Err()) + return out +} + +func queryOutbox(t *testing.T, sqlDB *sql.DB, where string, args ...any) []db.NotificationOutbox { + t.Helper() + + query := "SELECT " + outboxColumns + " FROM notification_outbox WHERE " + where + rows, err := sqlDB.Query(query, args...) + require.NoError(t, err) + return scanOutboxRows(t, rows) +} + +// tableCount counts rows in a named table. table and where are trusted literals +// supplied by the tests. +func tableCount(t *testing.T, sqlDB *sql.DB, table, where string, args ...any) int64 { + t.Helper() + + var n int64 + require.NoError(t, sqlDB.QueryRow("SELECT count(*) FROM "+table+" WHERE "+where, args...).Scan(&n)) + return n +} + +// insertIncidentStatus seeds one incident_status row and returns its id. +func insertIncidentStatus(t *testing.T, sqlDB *sql.DB, incidentID uint, status, text string) uint { + t.Helper() + + var id uint + require.NoError(t, sqlDB.QueryRow( + "INSERT INTO incident_status (incident_id, status, text, timestamp) VALUES ($1, $2, $3, now()) RETURNING id", + incidentID, status, text).Scan(&id)) + return id +} + +func outboxCount(t *testing.T, sqlDB *sql.DB, incidentID int) int64 { + t.Helper() + + var n int64 + require.NoError(t, sqlDB. + QueryRow("SELECT count(*) FROM notification_outbox WHERE incident_id = $1", incidentID). + Scan(&n)) + return n +} + +func outboxNotSentCount(t *testing.T, sqlDB *sql.DB, incidentID int) int64 { + t.Helper() + + var n int64 + require.NoError(t, sqlDB. + QueryRow("SELECT count(*) FROM notification_outbox WHERE incident_id = $1 AND status <> $2", + incidentID, db.NotificationStatusSent). + Scan(&n)) + return n +} + +func outboxRecipients(t *testing.T, sqlDB *sql.DB, incidentID int) []string { + t.Helper() + return recipientsOf(queryOutbox(t, sqlDB, "incident_id = $1", incidentID)) +} + +func outboxRecipientsByKind(t *testing.T, sqlDB *sql.DB, incidentID int, kind string) []string { + t.Helper() + return recipientsOf(queryOutbox(t, sqlDB, "incident_id = $1 AND kind = $2", incidentID, kind)) +} + +func recipientsOf(rows []db.NotificationOutbox) []string { + out := make([]string, 0, len(rows)) + for i := range rows { + out = append(out, rows[i].Recipient) + } + return out +} + +func fetchRow(t *testing.T, sqlDB *sql.DB, id uint) db.NotificationOutbox { + t.Helper() + + rows := queryOutbox(t, sqlDB, "id = $1", id) + require.Len(t, rows, 1) + return rows[0] +} + +func fetchByDedup(t *testing.T, sqlDB *sql.DB, dedup string) db.NotificationOutbox { + t.Helper() + + rows := queryOutbox(t, sqlDB, "dedup_key = $1", dedup) + require.Len(t, rows, 1) + return rows[0] +} + +// updateOutbox changes columns on the single row matched by whereCol without +// touching updated_at, so tests can craft ages and states. +func updateOutbox(t *testing.T, sqlDB *sql.DB, cols map[string]any, whereCol string, whereVal any) { + t.Helper() + + keys := make([]string, 0, len(cols)) + for k := range cols { + keys = append(keys, k) + } + sort.Strings(keys) + + set := make([]string, 0, len(keys)) + args := make([]any, 0, len(keys)+1) + for i, k := range keys { + set = append(set, fmt.Sprintf("%s = $%d", k, i+1)) + args = append(args, cols[k]) + } + args = append(args, whereVal) + + query := "UPDATE notification_outbox SET " + strings.Join(set, ", ") + + fmt.Sprintf(" WHERE %s = $%d", whereCol, len(keys)+1) + _, err := sqlDB.Exec(query, args...) + require.NoError(t, err) +} + +// setOutbox mutates an outbox row by dedup key. +func setOutbox(t *testing.T, sqlDB *sql.DB, dedup string, cols map[string]any) { + t.Helper() + + if len(cols) == 0 { + return + } + updateOutbox(t, sqlDB, cols, "dedup_key", dedup) +} diff --git a/tests/rbac_admin_only_test.go b/tests/rbac_admin_only_test.go index cfda711..ee68b4f 100644 --- a/tests/rbac_admin_only_test.go +++ b/tests/rbac_admin_only_test.go @@ -25,6 +25,7 @@ func initTestsAdminOnly(t *testing.T) *gin.Engine { d, err := db.New(&conf.Config{DB: databaseURL}) require.NoError(t, err) + t.Cleanup(func() { _ = d.Close() }) gin.SetMode(gin.TestMode) r := gin.Default() diff --git a/tests/rbac_helpers_test.go b/tests/rbac_helpers_test.go index 7b90f35..89e90d5 100644 --- a/tests/rbac_helpers_test.go +++ b/tests/rbac_helpers_test.go @@ -51,6 +51,7 @@ func initRBACTests(t *testing.T) *gin.Engine { d, err := db.New(&conf.Config{DB: databaseURL}) require.NoError(t, err) + t.Cleanup(func() { _ = d.Close() }) gin.SetMode(gin.TestMode) r := gin.Default() From 90306b67a055cef9689b516da5084438f429043f Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:43:08 +0200 Subject: [PATCH 06/10] Harden the Ent incident writers and clear the lint findings - saveIncidentFull refuses a nil start_date instead of persisting the zero time, and reconciles incident_component_relation against the loaded component set so the association is idempotent - split saveIncidentFull, modifyIncident and Enqueue so gocognit stays under the repository limit, and justify the pgx blank import for revive - statusesByIncident batches its incident_status lookup, and the unused GetOpenedIncidentsWithComponent is removed Verified with go build ./..., go vet ./..., go test ./internal/... -count 1 and golangci-lint run. --- internal/db/db.go | 84 +++++++++++++------------------------ internal/db/errors.go | 1 + internal/db/mappers.go | 26 ++++++++---- internal/db/notification.go | 69 +++++++++++++++--------------- internal/db/write.go | 80 +++++++++++++++++++++++++++++------ 5 files changed, 150 insertions(+), 110 deletions(-) diff --git a/internal/db/db.go b/internal/db/db.go index 18b5e7d..4ed64ce 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -10,6 +10,7 @@ import ( "entgo.io/ent/dialect" entsql "entgo.io/ent/dialect/sql" + // Registered for its side effect: sql.Open("pgx", ...) needs the pgx database/sql driver. _ "github.com/jackc/pgx/v5/stdlib" "github.com/stackmon/otc-status-dashboard/ent" @@ -397,13 +398,39 @@ func (db *DB) modifyIncident(ctx context.Context, c *ent.Client, inc *Incident) now := time.Now().UTC() - // A struct-based update writes the non-zero fields only, so nil pointers and - // empty scalars are left untouched, mirroring the previous ORM behaviour. update := c.Incident.Update().Where(incident.IDEQ(int(inc.ID))) if inc.Type == event.TypeMaintenance { update.Where(incident.VersionEQ(expectedVersion)) } + applyIncidentPatch(update, inc) + update.SetVersion(newVersion).SetModifiedAt(now) + + affected, err := update.Save(ctx) + if err != nil { + return err + } + if inc.Type == event.TypeMaintenance && affected == 0 { + return ErrVersionConflict + } + for i := range inc.Statuses { + if inc.Statuses[i].ID != 0 { + continue + } + id, errStatus := insertIncidentStatus(ctx, c, &inc.Statuses[i], inc.ID) + if errStatus != nil { + return errStatus + } + inc.Statuses[i].ID = uint(id) + inc.Statuses[i].IncidentID = inc.ID + } + + return nil +} + +// applyIncidentPatch sets the non-zero fields only, so nil pointers and empty +// scalars are left untouched, mirroring the previous ORM behaviour. +func applyIncidentPatch(update *ent.IncidentUpdate, inc *Incident) { if inc.Text != nil { update.SetText(*inc.Text) } @@ -437,29 +464,6 @@ func (db *DB) modifyIncident(ctx context.Context, c *ent.Client, inc *Incident) if inc.ContactEmail != nil { update.SetContactEmail(*inc.ContactEmail) } - update.SetVersion(newVersion).SetModifiedAt(now) - - affected, err := update.Save(ctx) - if err != nil { - return err - } - if inc.Type == event.TypeMaintenance && affected == 0 { - return ErrVersionConflict - } - - for i := range inc.Statuses { - if inc.Statuses[i].ID != 0 { - continue - } - id, errStatus := insertIncidentStatus(ctx, c, &inc.Statuses[i], inc.ID) - if errStatus != nil { - return errStatus - } - inc.Statuses[i].ID = uint(id) - inc.Statuses[i].IncidentID = inc.ID - } - - return nil } // AddComponentToIncident adds a component and a status update to an incident using optimistic locking. @@ -625,36 +629,6 @@ func (db *DB) GetIncidentsByComponentAttr(attr *ComponentAttr, params ...*Incide return db.incidentsByIDs(ctx, ids) } -func (db *DB) GetOpenedIncidentsWithComponent(_ string, _ []ComponentAttr) (*Incident, error) { - ctx := context.Background() - - // Legacy behaviour kept as-is: the component probe is not restricted to any - // name or attribute and the incident lookup carries no component filter, so - // this returns an arbitrary open incident. - if _, err := db.e.Component.Query().Exist(ctx); err != nil { - return nil, err - } - - e, err := db.e.Incident.Query(). - WithComponents(func(q *ent.ComponentQuery) { - q.Select(component.FieldID) - }). - Order(incident.ByID(entsql.OrderAsc())). - First(ctx) - if err != nil { - return nil, err - } - - inc := incidentFromEnt(e) - grouped, err := db.statusesByIncident(ctx, []int{e.ID}) - if err != nil { - return nil, err - } - attachStatuses([]*Incident{inc}, grouped) - - return inc, nil -} - func (db *DB) GetComponent(id int) (*Component, error) { e, err := db.e.Component.Query(). Where(component.IDEQ(id)). diff --git a/internal/db/errors.go b/internal/db/errors.go index ea3370d..69f67a9 100644 --- a/internal/db/errors.go +++ b/internal/db/errors.go @@ -5,6 +5,7 @@ import "errors" var ErrDBComponentDSNotExist = errors.New("component does not exist") var ErrDBComponentExists = errors.New("component exists") var ErrDBIncidentDSNotExist = errors.New("incident does not exist") +var ErrIncidentStartDateRequired = errors.New("incident start_date is required") var ErrDBEventUpdateDSNotExist = errors.New("update does not exist") var ErrDBIncidentFilterActiveFalse = errors.New("filter for inactive incidents is restricted") var ErrVersionConflict = errors.New("version conflict") diff --git a/internal/db/mappers.go b/internal/db/mappers.go index ebbe78d..62fa588 100644 --- a/internal/db/mappers.go +++ b/internal/db/mappers.go @@ -109,6 +109,10 @@ func componentAttrFromEnt(e *ent.ComponentAttr) ComponentAttr { } } +// incidentStatusChunkSize caps the IN predicate because PostgreSQL rejects +// queries with more than 65535 bound parameters. +const incidentStatusChunkSize = 1000 + // statusesByIncident loads the update history for the given incidents. The Ent // schema has no status edge (production carries no foreign key on // incident_status), so callers attach the result themselves. @@ -118,16 +122,20 @@ func (db *DB) statusesByIncident(ctx context.Context, ids []int) (map[int][]Inci return grouped, nil } - rows, err := db.e.IncidentStatus.Query(). - Where(incidentstatus.IncidentIDIn(ids...)). - Order(incidentstatus.ByID(entsql.OrderAsc())). - All(ctx) - if err != nil { - return nil, err - } + for start := 0; start < len(ids); start += incidentStatusChunkSize { + end := min(start+incidentStatusChunkSize, len(ids)) - for _, r := range rows { - grouped[r.IncidentID] = append(grouped[r.IncidentID], incidentStatusFromEnt(r)) + rows, err := db.e.IncidentStatus.Query(). + Where(incidentstatus.IncidentIDIn(ids[start:end]...)). + Order(incidentstatus.ByID(entsql.OrderAsc())). + All(ctx) + if err != nil { + return nil, err + } + + for _, r := range rows { + grouped[r.IncidentID] = append(grouped[r.IncidentID], incidentStatusFromEnt(r)) + } } return grouped, nil diff --git a/internal/db/notification.go b/internal/db/notification.go index 4440ae6..05cbdca 100644 --- a/internal/db/notification.go +++ b/internal/db/notification.go @@ -56,43 +56,46 @@ func (db *DB) Enqueue(ctx context.Context, tx *Tx, row NotificationOutbox) error return ErrNotificationDuplicate } - create := c.NotificationOutbox.Create(). - SetKind(row.Kind). - SetIncidentID(int(row.IncidentID)). - SetRecipient(row.Recipient). - SetPayload(row.Payload). - SetChangeID(row.ChangeID). - SetDedupKey(row.DedupKey) - if row.Status != "" { - create.SetStatus(row.Status) - } - if row.Attempts != 0 { - create.SetAttempts(row.Attempts) - } - if row.NextAttemptAt != nil { - create.SetNextAttemptAt(*row.NextAttemptAt) - } - if row.LockedBy != nil { - create.SetLockedBy(*row.LockedBy) - } - if row.LockedAt != nil { - create.SetLockedAt(*row.LockedAt) - } - if row.LastError != nil { - create.SetLastError(*row.LastError) - } - if !row.CreatedAt.IsZero() { - create.SetCreatedAt(row.CreatedAt) - } - if !row.UpdatedAt.IsZero() { - create.SetUpdatedAt(row.UpdatedAt) - } - - _, err = create.Save(ctx) + _, err = newOutboxCreate(c, row).Save(ctx) return err }) } +func newOutboxCreate(c *ent.Client, row NotificationOutbox) *ent.NotificationOutboxCreate { + create := c.NotificationOutbox.Create(). + SetKind(row.Kind). + SetIncidentID(int(row.IncidentID)). + SetRecipient(row.Recipient). + SetPayload(row.Payload). + SetChangeID(row.ChangeID). + SetDedupKey(row.DedupKey) + if row.Status != "" { + create.SetStatus(row.Status) + } + if row.Attempts != 0 { + create.SetAttempts(row.Attempts) + } + if row.NextAttemptAt != nil { + create.SetNextAttemptAt(*row.NextAttemptAt) + } + if row.LockedBy != nil { + create.SetLockedBy(*row.LockedBy) + } + if row.LockedAt != nil { + create.SetLockedAt(*row.LockedAt) + } + if row.LastError != nil { + create.SetLastError(*row.LastError) + } + if !row.CreatedAt.IsZero() { + create.SetCreatedAt(row.CreatedAt) + } + if !row.UpdatedAt.IsZero() { + create.SetUpdatedAt(row.UpdatedAt) + } + return create +} + // ClaimPending claims a batch of due rows for processing. // It must use `FOR UPDATE SKIP LOCKED` semantics and mark rows as processing, // increment attempts, and store lease metadata. diff --git a/internal/db/write.go b/internal/db/write.go index 201c77e..92ae25d 100644 --- a/internal/db/write.go +++ b/internal/db/write.go @@ -73,19 +73,34 @@ func dropIncidentComponent(inc *Incident, componentID uint) { inc.Components = kept } -// saveIncidentFull writes every incident column and upserts the assocations, which -// is what the previous ORM Save did for these flows: nil optional values clear the -// column instead of being skipped. +// saveIncidentFull writes every incident column and reconciles the component +// associations. nil optional values clear the column instead of being skipped. func saveIncidentFull(ctx context.Context, c *ent.Client, inc *Incident) error { + if inc.StartDate == nil { + return ErrIncidentStartDateRequired + } + update := c.Incident.UpdateOneID(int(inc.ID)). SetText(valueOr(inc.Text, "")). - SetStartDate(valueOr(inc.StartDate, time.Time{})). + SetStartDate(*inc.StartDate). SetImpact(valueOr(inc.Impact, 0)). SetSystem(inc.System). SetType(incident.Type(inc.Type)). SetStatus(string(inc.Status)). SetVersion(valueOr(inc.Version, 1)) + applyIncidentOptionalColumns(update, inc) + + if _, err := update.Save(ctx); err != nil { + return err + } + if err := reconcileIncidentComponents(ctx, c, inc); err != nil { + return err + } + return insertNewIncidentStatuses(ctx, c, inc) +} + +func applyIncidentOptionalColumns(update *ent.IncidentUpdateOne, inc *Incident) { if inc.Description != nil { update.SetDescription(*inc.Description) } else { @@ -121,23 +136,63 @@ func saveIncidentFull(ctx context.Context, c *ent.Client, inc *Incident) error { } else { update.ClearContactEmail() } +} - if _, err := update.Save(ctx); err != nil { +// reconcileIncidentComponents makes the stored component edge match inc.Components +// exactly; every incident read loads the edge unfiltered, so inc.Components is the +// full authoritative set. +func reconcileIncidentComponents(ctx context.Context, c *ent.Client, inc *Incident) error { + want := make(map[int]struct{}, len(inc.Components)) + for i := range inc.Components { + if inc.Components[i].ID != 0 { + want[int(inc.Components[i].ID)] = struct{}{} + } + } + + currentIDs, err := c.Incident.Query(). + Where(incident.IDEQ(int(inc.ID))). + QueryComponents(). + IDs(ctx) + if err != nil { return err } - componentIDs := make([]int, 0, len(inc.Components)) - for i := range inc.Components { - if inc.Components[i].ID != 0 { - componentIDs = append(componentIDs, int(inc.Components[i].ID)) + current := make(map[int]struct{}, len(currentIDs)) + var extra []int + for _, id := range currentIDs { + current[id] = struct{}{} + if _, ok := want[id]; !ok { + extra = append(extra, id) } } - if len(componentIDs) > 0 { - if _, err := c.Incident.UpdateOneID(int(inc.ID)).AddComponentIDs(componentIDs...).Save(ctx); err != nil { - return err + + var missing []int + for i := range inc.Components { + id := int(inc.Components[i].ID) + if id == 0 { + continue + } + if _, ok := current[id]; !ok { + missing = append(missing, id) } } + if len(extra) == 0 && len(missing) == 0 { + return nil + } + + update := c.Incident.UpdateOneID(int(inc.ID)) + if len(extra) > 0 { + update.RemoveComponentIDs(extra...) + } + if len(missing) > 0 { + update.AddComponentIDs(missing...) + } + _, err = update.Save(ctx) + return err +} + +func insertNewIncidentStatuses(ctx context.Context, c *ent.Client, inc *Incident) error { for i := range inc.Statuses { if inc.Statuses[i].ID != 0 { continue @@ -149,7 +204,6 @@ func saveIncidentFull(ctx context.Context, c *ent.Client, inc *Incident) error { inc.Statuses[i].ID = uint(id) inc.Statuses[i].IncidentID = inc.ID } - return nil } From 41a485c57582e14852344b25a12e1f2bff74aba2 Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:48:27 +0200 Subject: [PATCH 07/10] Replicate the incident before-save hooks in the full save - saveIncidentFull now stamps modified_at on every save and defaults a nil created_at to now, matching the GORM BeforeSave/BeforeUpdate hooks, and mirrors both onto the returned struct - reject a nil or empty text, which the Ent schema declares NotEmpty, with ErrIncidentTextRequired in both the create and full-save paths Verified with go build ./..., go vet ./..., go test ./internal/... -count 1 and golangci-lint run. --- internal/db/db.go | 6 +++++- internal/db/errors.go | 1 + internal/db/write.go | 30 +++++++++++++++++------------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/internal/db/db.go b/internal/db/db.go index 4ed64ce..7c494f7 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -310,8 +310,12 @@ func (db *DB) SaveIncidentTx(tx *Tx, inc *Incident) (uint, error) { inc.CreatedAt = &createdAt inc.ModifiedAt = &modifiedAt + if inc.Text == nil || *inc.Text == "" { + return 0, ErrIncidentTextRequired + } + create := c.Incident.Create(). - SetText(valueOr(inc.Text, "")). + SetText(*inc.Text). SetStartDate(valueOr(inc.StartDate, now)). SetImpact(valueOr(inc.Impact, 0)). SetSystem(inc.System). diff --git a/internal/db/errors.go b/internal/db/errors.go index 69f67a9..43002bf 100644 --- a/internal/db/errors.go +++ b/internal/db/errors.go @@ -6,6 +6,7 @@ var ErrDBComponentDSNotExist = errors.New("component does not exist") var ErrDBComponentExists = errors.New("component exists") var ErrDBIncidentDSNotExist = errors.New("incident does not exist") var ErrIncidentStartDateRequired = errors.New("incident start_date is required") +var ErrIncidentTextRequired = errors.New("incident text is required") var ErrDBEventUpdateDSNotExist = errors.New("update does not exist") var ErrDBIncidentFilterActiveFalse = errors.New("filter for inactive incidents is restricted") var ErrVersionConflict = errors.New("version conflict") diff --git a/internal/db/write.go b/internal/db/write.go index 92ae25d..0a4aba3 100644 --- a/internal/db/write.go +++ b/internal/db/write.go @@ -74,20 +74,34 @@ func dropIncidentComponent(inc *Incident, componentID uint) { } // saveIncidentFull writes every incident column and reconciles the component -// associations. nil optional values clear the column instead of being skipped. +// associations. created_at defaults to now and modified_at is stamped on every +// save; nil optional values clear their column instead of being skipped. func saveIncidentFull(ctx context.Context, c *ent.Client, inc *Incident) error { + if inc.Text == nil || *inc.Text == "" { + return ErrIncidentTextRequired + } if inc.StartDate == nil { return ErrIncidentStartDateRequired } + now := time.Now().UTC() + createdAt := now + if inc.CreatedAt != nil { + createdAt = *inc.CreatedAt + } + inc.CreatedAt = &createdAt + inc.ModifiedAt = &now + update := c.Incident.UpdateOneID(int(inc.ID)). - SetText(valueOr(inc.Text, "")). + SetText(*inc.Text). SetStartDate(*inc.StartDate). SetImpact(valueOr(inc.Impact, 0)). SetSystem(inc.System). SetType(incident.Type(inc.Type)). SetStatus(string(inc.Status)). - SetVersion(valueOr(inc.Version, 1)) + SetVersion(valueOr(inc.Version, 1)). + SetCreatedAt(createdAt). + SetModifiedAt(now) applyIncidentOptionalColumns(update, inc) @@ -111,16 +125,6 @@ func applyIncidentOptionalColumns(update *ent.IncidentUpdateOne, inc *Incident) } else { update.ClearEndDate() } - if inc.CreatedAt != nil { - update.SetCreatedAt(*inc.CreatedAt) - } else { - update.ClearCreatedAt() - } - if inc.ModifiedAt != nil { - update.SetModifiedAt(*inc.ModifiedAt) - } else { - update.ClearModifiedAt() - } if inc.DeletedAt != nil { update.SetDeletedAt(*inc.DeletedAt) } else { From 85d11740e392226b9e870852c8083aeb25233bad Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 22:14:41 +0200 Subject: [PATCH 08/10] Run the storage integration suite in CI and fix its stale patch cases - add a go-test-acc job that uses a runner-provided postgres service and loads tests/testdata/dump_test.sql before the suite, so tests/ actually runs without an external database - fix four stale PATCH negative assertions in tests/v2_test.go and tests/v2_events_test.go: the payloads changed the event type on an incident, so the type-immutability check always fired first Verified with make test-acc against the restored fixture (142 tests pass, internal/db coverage 80.1%). --- .github/workflows/ci.yaml | 28 ++++++++++++++++++++++++++++ tests/v2_events_test.go | 14 +++++++------- tests/v2_test.go | 14 +++++++------- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9de40cb..2f86e80 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,3 +39,31 @@ jobs: with: go-version: ${{ env.GO_VERSION }} - run: make test + + test-acc: + name: go-test-acc + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15-alpine + env: + POSTGRES_USER: pg + POSTGRES_PASSWORD: pass + POSTGRES_DB: status_dashboard + ports: + - 5432:5432 + options: >- + --health-cmd "pg_isready -U pg" + --health-interval 10s + --health-timeout 5s + --health-retries 10 + env: + SD_TEST_DSN: postgres://pg:pass@localhost:5432/status_dashboard?sslmode=disable + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-go@v7 + with: + go-version: ${{ env.GO_VERSION }} + - name: Load the test fixture + run: psql "$SD_TEST_DSN" -v ON_ERROR_STOP=1 -q -f tests/testdata/dump_test.sql + - run: make test-acc diff --git a/tests/v2_events_test.go b/tests/v2_events_test.go index d37e512..59c63cb 100644 --- a/tests/v2_events_test.go +++ b/tests/v2_events_test.go @@ -362,19 +362,19 @@ func TestV2PatchEventHandlerNegative(t *testing.T) { "version": %d }`, version) jsWrongOpenedStatusForChangingImpact := fmt.Sprintf(`{ -"impact": 0, +"impact": 2, "message": "Any message why the event was updated.", "status": "analysing", "update_date": "2024-12-11T14:46:03.877Z", -"type": "maintenance", +"type": "incident", "version": %d }`, version) - jsWrongOpenedMaintenanceImpact := fmt.Sprintf(`{ + jsImpactToZeroForIncident := fmt.Sprintf(`{ "impact": 0, "message": "Any message why the event was updated.", "status": "impact changed", "update_date": "2024-12-11T14:46:03.877Z", - "type": "maintenance", + "type": "incident", "version": %d }`, version) testCases := map[string]*testCase{ @@ -393,9 +393,9 @@ func TestV2PatchEventHandlerNegative(t *testing.T) { Expected: `{"errMsg":"wrong status for changing impact"}`, ExpectedCode: 400, }, - "negative testcase, can't change impact from incident to maintenance": { - JSON: jsWrongOpenedMaintenanceImpact, - Expected: `{"errMsg":"can not change impact to 0"}`, + "negative testcase, can not set impact to 0 on an incident": { + JSON: jsImpactToZeroForIncident, + Expected: `{"errMsg":"impact must be 0 for type 'maintenance' or 'info' and gt 0 for 'incident'"}`, ExpectedCode: 400, }, } diff --git a/tests/v2_test.go b/tests/v2_test.go index 069bd78..c0348d7 100644 --- a/tests/v2_test.go +++ b/tests/v2_test.go @@ -479,19 +479,19 @@ func TestV2PatchIncidentHandlerNegative(t *testing.T) { "version": 1 }` jsWrongOpenedStatusForChangingImpact := `{ - "impact": 0, + "impact": 2, "message": "Any message why the event was updated.", "status": "analysing", "update_date": "2024-12-11T14:46:03.877Z", - "type": "maintenance", + "type": "incident", "version": 1 }` - jsWrongOpenedMaintenanceImpact := `{ + jsImpactToZeroForIncident := `{ "impact": 0, "message": "Any message why the event was updated.", "status": "impact changed", "update_date": "2024-12-11T14:46:03.877Z", - "type": "maintenance", + "type": "incident", "version": 1 }` testCases := map[string]*testCase{ @@ -510,9 +510,9 @@ func TestV2PatchIncidentHandlerNegative(t *testing.T) { Expected: `{"errMsg":"wrong status for changing impact"}`, ExpectedCode: 400, }, - "negative testcase, can't change impact from incident to maintenance": { - JSON: jsWrongOpenedMaintenanceImpact, - Expected: `{"errMsg":"can not change impact to 0"}`, + "negative testcase, can not set impact to 0 on an incident": { + JSON: jsImpactToZeroForIncident, + Expected: `{"errMsg":"impact must be 0 for type 'maintenance' or 'info' and gt 0 for 'incident'"}`, ExpectedCode: 400, }, } From fa118472f0e08afa7b48971774d1e67dd83e2c99 Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 22:32:36 +0200 Subject: [PATCH 09/10] Make the storage integration suite repeatable and drop a dead patch error - remove the unreachable impact-to-zero branch in checkPatchDataForIncident and its sentinel: validateEffectiveTypeAndImpact already rejects an incident whose effective impact is 0, so the branch could never fire - let TestV2CreateComponentAndList own the component it creates (delete before, clean up after) and assert the fixture components by membership, and point TestV2GetComponentsAvailability at fixture component 1, so a second run on the same database passes instead of tripping over residue from the first Verified by running the suite twice in a row on the same database (both pass), plus go build, go vet, go test ./internal/... and golangci-lint. --- internal/api/errors/incident.go | 1 - internal/api/v2/v2.go | 4 --- tests/v2_test.go | 64 +++++++++++++++++++++++++++++---- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/internal/api/errors/incident.go b/internal/api/errors/incident.go index 6cbcc92..c06f264 100644 --- a/internal/api/errors/incident.go +++ b/internal/api/errors/incident.go @@ -38,7 +38,6 @@ var ErrIncidentPatchClosedStatus = errors.New("wrong status for closed incident" var ErrIncidentPatchOpenedStartDate = errors.New("can not change start date for open incident") var ErrIncidentPatchOpenedEndDateMissing = errors.New("wrong end date with resolved status") var ErrIncidentPatchImpactStatusWrong = errors.New("wrong status for changing impact") -var ErrIncidentPatchImpactToZeroForbidden = errors.New("can not change impact to 0") var ErrIncidentPatchTypeForbidden = errors.New("can not change event type") var ErrMaintenanceEndDateEmpty = errors.New("maintenance end_date is empty") diff --git a/internal/api/v2/v2.go b/internal/api/v2/v2.go index 123c553..68f205d 100644 --- a/internal/api/v2/v2.go +++ b/internal/api/v2/v2.go @@ -1288,10 +1288,6 @@ func checkPatchDataForIncident(incoming *PatchIncidentData, stored *db.Incident) return apiErrors.ErrIncidentPatchImpactStatusWrong } - if incoming.Impact != nil && *incoming.Impact != *stored.Impact && *incoming.Impact == 0 { - return apiErrors.ErrIncidentPatchImpactToZeroForbidden - } - if incoming.StartDate != nil { return apiErrors.ErrIncidentPatchOpenedStartDate } diff --git a/tests/v2_test.go b/tests/v2_test.go index c0348d7..14b4488 100644 --- a/tests/v2_test.go +++ b/tests/v2_test.go @@ -92,15 +92,50 @@ func TestV2GetComponentsHandler(t *testing.T) { t.Log("start to test GET /v2/components") r := initTests(t) - var response = `[{"id":1,"name":"Cloud Container Engine","attributes":[{"name":"region","value":"EU-DE"},{"name":"category","value":"Container"},{"name":"type","value":"cce"}]},{"id":2,"name":"Cloud Container Engine","attributes":[{"name":"region","value":"EU-NL"},{"name":"category","value":"Container"},{"name":"type","value":"cce"}]},{"id":3,"name":"Elastic Cloud Server","attributes":[{"name":"region","value":"EU-DE"},{"name":"category","value":"Compute"},{"name":"type","value":"ecs"}]},{"id":4,"name":"Elastic Cloud Server","attributes":[{"name":"region","value":"EU-NL"},{"name":"category","value":"Compute"},{"name":"type","value":"ecs"}]},{"id":5,"name":"Distributed Cache Service","attributes":[{"name":"region","value":"EU-DE"},{"name":"category","value":"Database"},{"name":"type","value":"dcs"}]},{"id":6,"name":"Distributed Cache Service","attributes":[{"name":"region","value":"EU-NL"},{"name":"category","value":"Database"},{"name":"type","value":"dcs"}]}]` - w := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/v2/components", nil) r.ServeHTTP(w, req) - assert.Equal(t, 200, w.Code) - assert.Equal(t, response, w.Body.String()) + require.Equal(t, 200, w.Code) + + var components []v2.Component + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &components)) + + expected := []v2.Component{ + {ComponentID: v2.ComponentID{ID: 1}, Name: "Cloud Container Engine", Attributes: []v2.ComponentAttribute{ + {Name: "region", Value: "EU-DE"}, {Name: "category", Value: "Container"}, {Name: "type", Value: "cce"}, + }}, + {ComponentID: v2.ComponentID{ID: 2}, Name: "Cloud Container Engine", Attributes: []v2.ComponentAttribute{ + {Name: "region", Value: "EU-NL"}, {Name: "category", Value: "Container"}, {Name: "type", Value: "cce"}, + }}, + {ComponentID: v2.ComponentID{ID: 3}, Name: "Elastic Cloud Server", Attributes: []v2.ComponentAttribute{ + {Name: "region", Value: "EU-DE"}, {Name: "category", Value: "Compute"}, {Name: "type", Value: "ecs"}, + }}, + {ComponentID: v2.ComponentID{ID: 4}, Name: "Elastic Cloud Server", Attributes: []v2.ComponentAttribute{ + {Name: "region", Value: "EU-NL"}, {Name: "category", Value: "Compute"}, {Name: "type", Value: "ecs"}, + }}, + {ComponentID: v2.ComponentID{ID: 5}, Name: "Distributed Cache Service", Attributes: []v2.ComponentAttribute{ + {Name: "region", Value: "EU-DE"}, {Name: "category", Value: "Database"}, {Name: "type", Value: "dcs"}, + }}, + {ComponentID: v2.ComponentID{ID: 6}, Name: "Distributed Cache Service", Attributes: []v2.ComponentAttribute{ + {Name: "region", Value: "EU-NL"}, {Name: "category", Value: "Database"}, {Name: "type", Value: "dcs"}, + }}, + } + + for _, want := range expected { + found := false + for i := range components { + if components[i].ID != want.ID { + continue + } + assert.Equal(t, want.Name, components[i].Name) + assert.ElementsMatch(t, want.Attributes, components[i].Attributes) + found = true + break + } + assert.True(t, found, "component %d (%s) not found in response", want.ID, want.Name) + } } func TestV2PostIncidentsHandlerNegative(t *testing.T) { @@ -842,14 +877,29 @@ func v2PatchIncident(t *testing.T, r *gin.Engine, inc *v2.Incident, status ...ev *inc = updated } +func deleteComponentByName(t *testing.T, name string) { + t.Helper() + + sqlDB := openRawDB(t) + _, err := sqlDB.Exec( + "DELETE FROM component_attribute WHERE component_id IN (SELECT id FROM component WHERE name = $1)", name) + require.NoError(t, err) + _, err = sqlDB.Exec("DELETE FROM component WHERE name = $1", name) + require.NoError(t, err) +} + func TestV2CreateComponentAndList(t *testing.T) { t.Log("start to test component creation and listing") r := initTests(t) + const componentName = "Domain Name System" + deleteComponentByName(t, componentName) + t.Cleanup(func() { deleteComponentByName(t, componentName) }) + // Test case 1: Successful component creation t.Log("Test case 1: Create new component successfully") newComponent := v2.PostComponentData{ - Name: "Domain Name System", + Name: componentName, Attributes: []v2.ComponentAttribute{ {Name: "type", Value: "dns"}, {Name: "region", Value: "EU-DE"}, @@ -1303,7 +1353,7 @@ func TestV2GetComponentsAvailability(t *testing.T) { // Incident preparation t.Log("create an incident") - components := []int{7} + components := []int{1} impact := 3 system := false now := time.Now().UTC() @@ -1386,7 +1436,7 @@ func TestV2GetComponentsAvailability(t *testing.T) { } for _, compAvail := range availability.Data { - if compAvail.ID == 7 { + if compAvail.ID == 1 { checkComponentAvailability(t, compAvail, targetMonths) } } From 8df59859626a9dd60101dc1fa569056cf463e303 Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Sat, 3 Oct 2026 22:48:32 +0200 Subject: [PATCH 10/10] Address the remaining storage review findings and add CODEOWNERS - Enqueue maps a unique-constraint failure on dedup_key to ErrNotificationDuplicate, so a duplicate that loses the check-then-insert race is no longer reported to the caller as a fatal error - notification_outbox locked_by and last_error are nillable, keeping SQL NULL distinct from an empty string; the generated Ent code is regenerated - SaveIncidentTx validates before it mutates the caller's struct, incidentsByIDs chunks its id predicate, and reconcileIncidentComponents documents that it does not create components - CI regenerates the Ent code and fails when ent/ is out of sync with the schema Verified with go build, go vet, go test ./internal/..., golangci-lint, and the integration suite twice in a row against the same database. --- .github/CODEOWNERS | 1 + .github/workflows/ci.yaml | 11 +++++++++++ ent/mutation.go | 4 ++-- ent/notificationoutbox.go | 22 +++++++++++++-------- ent/notificationoutbox_create.go | 4 ++-- ent/schema/notificationoutbox.go | 4 ++-- internal/db/db.go | 8 ++++---- internal/db/mappers.go | 8 ++------ internal/db/notification.go | 9 +++++++-- internal/db/raw.go | 34 ++++++++++++++++++++------------ internal/db/write.go | 4 ++-- 11 files changed, 68 insertions(+), 41 deletions(-) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..9b78959 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +@Aloento diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2f86e80..8019bcf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,6 +30,17 @@ jobs: with: version: ${{ env.GO_LINT }} + ent-codegen: + name: ent-codegen + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-go@v7 + with: + go-version: ${{ env.GO_VERSION }} + - run: go generate ./ent + - run: git diff --exit-code -- ent/ + test: name: go-test runs-on: ubuntu-latest diff --git a/ent/mutation.go b/ent/mutation.go index f6d526a..f5d3b9b 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -4142,7 +4142,7 @@ func (m *NotificationOutboxMutation) LockedBy() (r string, exists bool) { // OldLockedBy returns the old "locked_by" field's value of the NotificationOutbox entity. // If the NotificationOutbox 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 *NotificationOutboxMutation) OldLockedBy(ctx context.Context) (v string, err error) { +func (m *NotificationOutboxMutation) OldLockedBy(ctx context.Context) (v *string, err error) { if !m.op.Is(OpUpdateOne) { return v, errors.New("OldLockedBy is only allowed on UpdateOne operations") } @@ -4240,7 +4240,7 @@ func (m *NotificationOutboxMutation) LastError() (r string, exists bool) { // OldLastError returns the old "last_error" field's value of the NotificationOutbox entity. // If the NotificationOutbox 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 *NotificationOutboxMutation) OldLastError(ctx context.Context) (v string, err error) { +func (m *NotificationOutboxMutation) OldLastError(ctx context.Context) (v *string, err error) { if !m.op.Is(OpUpdateOne) { return v, errors.New("OldLastError is only allowed on UpdateOne operations") } diff --git a/ent/notificationoutbox.go b/ent/notificationoutbox.go index b34cf51..1e2883f 100644 --- a/ent/notificationoutbox.go +++ b/ent/notificationoutbox.go @@ -38,11 +38,11 @@ type NotificationOutbox struct { // NextAttemptAt holds the value of the "next_attempt_at" field. NextAttemptAt time.Time `json:"next_attempt_at,omitempty"` // LockedBy holds the value of the "locked_by" field. - LockedBy string `json:"locked_by,omitempty"` + LockedBy *string `json:"locked_by,omitempty"` // LockedAt holds the value of the "locked_at" field. LockedAt time.Time `json:"locked_at,omitempty"` // LastError holds the value of the "last_error" field. - LastError string `json:"last_error,omitempty"` + LastError *string `json:"last_error,omitempty"` // CreatedAt holds the value of the "created_at" field. CreatedAt time.Time `json:"created_at,omitempty"` // UpdatedAt holds the value of the "updated_at" field. @@ -167,7 +167,8 @@ func (_m *NotificationOutbox) assignValues(columns []string, values []any) error if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field locked_by", values[i]) } else if value.Valid { - _m.LockedBy = value.String + _m.LockedBy = new(string) + *_m.LockedBy = value.String } case notificationoutbox.FieldLockedAt: if value, ok := values[i].(*sql.NullTime); !ok { @@ -179,7 +180,8 @@ func (_m *NotificationOutbox) assignValues(columns []string, values []any) error if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field last_error", values[i]) } else if value.Valid { - _m.LastError = value.String + _m.LastError = new(string) + *_m.LastError = value.String } case notificationoutbox.FieldCreatedAt: if value, ok := values[i].(*sql.NullTime); !ok { @@ -261,14 +263,18 @@ func (_m *NotificationOutbox) String() string { builder.WriteString("next_attempt_at=") builder.WriteString(_m.NextAttemptAt.Format(time.ANSIC)) builder.WriteString(", ") - builder.WriteString("locked_by=") - builder.WriteString(_m.LockedBy) + if v := _m.LockedBy; v != nil { + builder.WriteString("locked_by=") + builder.WriteString(*v) + } builder.WriteString(", ") builder.WriteString("locked_at=") builder.WriteString(_m.LockedAt.Format(time.ANSIC)) builder.WriteString(", ") - builder.WriteString("last_error=") - builder.WriteString(_m.LastError) + if v := _m.LastError; v != nil { + builder.WriteString("last_error=") + builder.WriteString(*v) + } builder.WriteString(", ") builder.WriteString("created_at=") builder.WriteString(_m.CreatedAt.Format(time.ANSIC)) diff --git a/ent/notificationoutbox_create.go b/ent/notificationoutbox_create.go index 6963ca4..24663e4 100644 --- a/ent/notificationoutbox_create.go +++ b/ent/notificationoutbox_create.go @@ -327,7 +327,7 @@ func (_c *NotificationOutboxCreate) createSpec() (*NotificationOutbox, *sqlgraph } if value, ok := _c.mutation.LockedBy(); ok { _spec.SetField(notificationoutbox.FieldLockedBy, field.TypeString, value) - _node.LockedBy = value + _node.LockedBy = &value } if value, ok := _c.mutation.LockedAt(); ok { _spec.SetField(notificationoutbox.FieldLockedAt, field.TypeTime, value) @@ -335,7 +335,7 @@ func (_c *NotificationOutboxCreate) createSpec() (*NotificationOutbox, *sqlgraph } if value, ok := _c.mutation.LastError(); ok { _spec.SetField(notificationoutbox.FieldLastError, field.TypeString, value) - _node.LastError = value + _node.LastError = &value } if value, ok := _c.mutation.CreatedAt(); ok { _spec.SetField(notificationoutbox.FieldCreatedAt, field.TypeTime, value) diff --git a/ent/schema/notificationoutbox.go b/ent/schema/notificationoutbox.go index c59c2aa..22fd087 100644 --- a/ent/schema/notificationoutbox.go +++ b/ent/schema/notificationoutbox.go @@ -46,11 +46,11 @@ func (NotificationOutbox) Fields() []ent.Field { SchemaType(map[string]string{"postgres": "integer"}), field.Time("next_attempt_at").Optional(). SchemaType(map[string]string{"postgres": "timestamptz"}), - field.String("locked_by").Optional(). + field.String("locked_by").Optional().Nillable(). SchemaType(map[string]string{"postgres": "varchar(255)"}), field.Time("locked_at").Optional(). SchemaType(map[string]string{"postgres": "timestamptz"}), - field.Text("last_error").Optional(), + field.Text("last_error").Optional().Nillable(), field.Time("created_at"). Annotations(entsql.DefaultExpr("NOW()")). SchemaType(map[string]string{"postgres": "timestamptz"}), diff --git a/internal/db/db.go b/internal/db/db.go index 7c494f7..3cd0e86 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -294,6 +294,10 @@ func (db *DB) WithTx(ctx context.Context, fn func(tx *Tx) error) error { // SaveIncidentTx creates an incident using the provided transaction. func (db *DB) SaveIncidentTx(tx *Tx, inc *Incident) (uint, error) { + if inc.Text == nil || *inc.Text == "" { + return 0, ErrIncidentTextRequired + } + ctx := context.Background() c := db.clientFor(tx) @@ -310,10 +314,6 @@ func (db *DB) SaveIncidentTx(tx *Tx, inc *Incident) (uint, error) { inc.CreatedAt = &createdAt inc.ModifiedAt = &modifiedAt - if inc.Text == nil || *inc.Text == "" { - return 0, ErrIncidentTextRequired - } - create := c.Incident.Create(). SetText(*inc.Text). SetStartDate(valueOr(inc.StartDate, now)). diff --git a/internal/db/mappers.go b/internal/db/mappers.go index 62fa588..de76394 100644 --- a/internal/db/mappers.go +++ b/internal/db/mappers.go @@ -168,15 +168,11 @@ func notificationOutboxFromEnt(e *ent.NotificationOutbox) NotificationOutbox { if !e.NextAttemptAt.IsZero() { row.NextAttemptAt = &e.NextAttemptAt } - if e.LockedBy != "" { - row.LockedBy = &e.LockedBy - } + row.LockedBy = e.LockedBy if !e.LockedAt.IsZero() { row.LockedAt = &e.LockedAt } - if e.LastError != "" { - row.LastError = &e.LastError - } + row.LastError = e.LastError return row } diff --git a/internal/db/notification.go b/internal/db/notification.go index 05cbdca..9160797 100644 --- a/internal/db/notification.go +++ b/internal/db/notification.go @@ -56,8 +56,13 @@ func (db *DB) Enqueue(ctx context.Context, tx *Tx, row NotificationOutbox) error return ErrNotificationDuplicate } - _, err = newOutboxCreate(c, row).Save(ctx) - return err + if _, err = newOutboxCreate(c, row).Save(ctx); err != nil { + if ent.IsConstraintError(err) { + return ErrNotificationDuplicate + } + return err + } + return nil }) } diff --git a/internal/db/raw.go b/internal/db/raw.go index 34299a5..d4c61fb 100644 --- a/internal/db/raw.go +++ b/internal/db/raw.go @@ -10,6 +10,10 @@ import ( "github.com/stackmon/otc-status-dashboard/ent/incident" ) +// incidentIDChunkSize caps the IN predicate because PostgreSQL rejects +// queries with more than 65535 bound parameters. +const incidentIDChunkSize = 1000 + // incidentsByComponentAttrQuery lists incident ids matched through a component // attribute, applying the public visibility rules inline. const incidentsByComponentAttrQuery = ` @@ -49,20 +53,24 @@ func (db *DB) incidentsByIDs(ctx context.Context, ids []int) ([]*Incident, error return []*Incident{}, nil } - rows, err := db.e.Incident.Query(). - Where(incident.IDIn(ids...)). - WithComponents(func(q *ent.ComponentQuery) { - q.Select(component.FieldID, component.FieldName) - q.WithAttributes() - }). - All(ctx) - if err != nil { - return nil, err - } + byID := make(map[int]*Incident, len(ids)) + for start := 0; start < len(ids); start += incidentIDChunkSize { + end := min(start+incidentIDChunkSize, len(ids)) - byID := make(map[int]*Incident, len(rows)) - for _, row := range rows { - byID[row.ID] = incidentFromEnt(row) + rows, err := db.e.Incident.Query(). + Where(incident.IDIn(ids[start:end]...)). + WithComponents(func(q *ent.ComponentQuery) { + q.Select(component.FieldID, component.FieldName) + q.WithAttributes() + }). + All(ctx) + if err != nil { + return nil, err + } + + for _, row := range rows { + byID[row.ID] = incidentFromEnt(row) + } } incidents := make([]*Incident, 0, len(ids)) diff --git a/internal/db/write.go b/internal/db/write.go index 0a4aba3..8049afd 100644 --- a/internal/db/write.go +++ b/internal/db/write.go @@ -143,8 +143,8 @@ func applyIncidentOptionalColumns(update *ent.IncidentUpdateOne, inc *Incident) } // reconcileIncidentComponents makes the stored component edge match inc.Components -// exactly; every incident read loads the edge unfiltered, so inc.Components is the -// full authoritative set. +// exactly. Callers pass components that already exist, so only the join rows are +// reconciled: a component absent from the component table is not created. func reconcileIncidentComponents(ctx context.Context, c *ent.Client, inc *Incident) error { want := make(map[int]struct{}, len(inc.Components)) for i := range inc.Components {