try to use a LEFT JOIN

This commit is contained in:
Sebastien Blot 2022-07-22 08:59:56 +02:00
parent 42d5dd8e03
commit 319957e134
No known key found for this signature in database
GPG key ID: DFC2902F40449F6A
8 changed files with 172 additions and 18 deletions

View file

@ -47,6 +47,7 @@ func LoadTestConfig() csconfig.Config {
Type: "sqlite", Type: "sqlite",
DbPath: filepath.Join(tempDir, "ent"), DbPath: filepath.Join(tempDir, "ent"),
Flush: &flushConfig, Flush: &flushConfig,
//LogLevel: &log.AllLevels[log.DebugLevel],
} }
apiServerConfig := csconfig.LocalApiServerCfg{ apiServerConfig := csconfig.LocalApiServerCfg{
ListenURI: "http://127.0.0.1:8080", ListenURI: "http://127.0.0.1:8080",

View file

@ -207,7 +207,7 @@ func (c *Client) QueryExpiredDecisionsWithFilters(filters map[string][]string) (
return []*ent.Decision{}, errors.Wrap(QueryFail, "get expired decisions with filters") return []*ent.Decision{}, errors.Wrap(QueryFail, "get expired decisions with filters")
} }
query = query.Where(func(s *sql.Selector) { /*query = query.Where(func(s *sql.Selector) {
t := sql.Table(decision.Table).As("t1") t := sql.Table(decision.Table).As("t1")
subquery := sql.Select(s.C(decision.FieldValue)).From(t) subquery := sql.Select(s.C(decision.FieldValue)).From(t)
@ -226,7 +226,28 @@ func (c *Client) QueryExpiredDecisionsWithFilters(filters map[string][]string) (
s.Where(sql.NotExists(subquery)) s.Where(sql.NotExists(subquery))
}) })
data, err := query.Order(ent.Asc(decision.FieldValue), ent.Desc(decision.FieldUntil)).All(c.CTX) data, err := query.Order(ent.Asc(decision.FieldValue), ent.Desc(decision.FieldUntil)).All(c.CTX)*/
query.Modify(func(s *sql.Selector) {
t := sql.Table(decision.Table).As("t1")
p := []*sql.Predicate{
sql.ColumnsEQ(s.C(decision.FieldScope), t.C(decision.FieldScope)),
sql.ColumnsEQ(s.C(decision.FieldType), t.C(decision.FieldType)),
sql.ColumnsEQ(s.C(decision.FieldValue), t.C(decision.FieldValue)),
sql.GTE(t.C(decision.FieldUntil), now),
}
p = append(p, predicates...)
s.LeftJoin(t).
OnP(
sql.And(
p...,
)).
GroupBy(s.C(decision.FieldValue)).
Where(sql.IsNull(t.C(decision.FieldValue)))
})
data, err := query.All(c.CTX)
if err != nil { if err != nil {
c.Log.Warningf("QueryExpiredDecisionsWithFilters : %s", err) c.Log.Warningf("QueryExpiredDecisionsWithFilters : %s", err)
return []*ent.Decision{}, errors.Wrap(QueryFail, "expired decisions") return []*ent.Decision{}, errors.Wrap(QueryFail, "expired decisions")
@ -244,6 +265,7 @@ func (c *Client) QueryExpiredDecisionsSinceWithFilters(since time.Time, filters
query := c.Ent.Decision.Query().Where( query := c.Ent.Decision.Query().Where(
decision.UntilGTE(since), decision.UntilGTE(since),
decision.UntilLTE(now),
) )
query, predicates, err := BuildDecisionRequestWithFilter(query, filters) query, predicates, err := BuildDecisionRequestWithFilter(query, filters)
if err != nil { if err != nil {
@ -251,26 +273,25 @@ func (c *Client) QueryExpiredDecisionsSinceWithFilters(since time.Time, filters
return []*ent.Decision{}, errors.Wrap(QueryFail, "expired decisions with filters") return []*ent.Decision{}, errors.Wrap(QueryFail, "expired decisions with filters")
} }
query = query.Where(func(s *sql.Selector) { query.Modify(func(s *sql.Selector) {
t := sql.Table(decision.Table).As("t1") t := sql.Table(decision.Table).As("t1")
p := []*sql.Predicate{
subquery := sql.Select(s.C(decision.FieldValue)).From(t)
for _, pred := range predicates {
subquery.Where(pred)
}
subquery = subquery.Where(
sql.And(
sql.ColumnsEQ(s.C(decision.FieldScope), t.C(decision.FieldScope)), sql.ColumnsEQ(s.C(decision.FieldScope), t.C(decision.FieldScope)),
sql.ColumnsEQ(s.C(decision.FieldType), t.C(decision.FieldType)), sql.ColumnsEQ(s.C(decision.FieldType), t.C(decision.FieldType)),
sql.ColumnsEQ(s.C(decision.FieldValue), t.C(decision.FieldValue)), sql.ColumnsEQ(s.C(decision.FieldValue), t.C(decision.FieldValue)),
sql.GT(t.C(decision.FieldUntil), now), sql.GTE(t.C(decision.FieldUntil), now),
), }
) p = append(p, predicates...)
s.Where(sql.NotExists(subquery)) s.LeftJoin(t).
OnP(
sql.And(
p...,
)).
GroupBy(s.C(decision.FieldValue)).
Where(sql.IsNull(t.C(decision.FieldValue)))
}) })
data, err := query.Order(ent.Asc(decision.FieldValue), ent.Desc(decision.FieldUntil)).All(c.CTX) data, err := query.All(c.CTX)
if err != nil { if err != nil {
c.Log.Warningf("QueryExpiredDecisionsSinceWithFilters : %s", err) c.Log.Warningf("QueryExpiredDecisionsSinceWithFilters : %s", err)
return []*ent.Decision{}, errors.Wrap(QueryFail, "expired decisions with filters") return []*ent.Decision{}, errors.Wrap(QueryFail, "expired decisions with filters")

View file

@ -35,6 +35,7 @@ type AlertQuery struct {
withEvents *EventQuery withEvents *EventQuery
withMetas *MetaQuery withMetas *MetaQuery
withFKs bool withFKs bool
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -487,6 +488,9 @@ func (aq *AlertQuery) sqlAll(ctx context.Context) ([]*Alert, error) {
node.Edges.loadedTypes = loadedTypes node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values) return node.assignValues(columns, values)
} }
if len(aq.modifiers) > 0 {
_spec.Modifiers = aq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, aq.driver, _spec); err != nil { if err := sqlgraph.QueryNodes(ctx, aq.driver, _spec); err != nil {
return nil, err return nil, err
} }
@ -615,6 +619,9 @@ func (aq *AlertQuery) sqlAll(ctx context.Context) ([]*Alert, error) {
func (aq *AlertQuery) sqlCount(ctx context.Context) (int, error) { func (aq *AlertQuery) sqlCount(ctx context.Context) (int, error) {
_spec := aq.querySpec() _spec := aq.querySpec()
if len(aq.modifiers) > 0 {
_spec.Modifiers = aq.modifiers
}
_spec.Node.Columns = aq.fields _spec.Node.Columns = aq.fields
if len(aq.fields) > 0 { if len(aq.fields) > 0 {
_spec.Unique = aq.unique != nil && *aq.unique _spec.Unique = aq.unique != nil && *aq.unique
@ -693,6 +700,9 @@ func (aq *AlertQuery) sqlQuery(ctx context.Context) *sql.Selector {
if aq.unique != nil && *aq.unique { if aq.unique != nil && *aq.unique {
selector.Distinct() selector.Distinct()
} }
for _, m := range aq.modifiers {
m(selector)
}
for _, p := range aq.predicates { for _, p := range aq.predicates {
p(selector) p(selector)
} }
@ -710,6 +720,12 @@ func (aq *AlertQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector return selector
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (aq *AlertQuery) Modify(modifiers ...func(s *sql.Selector)) *AlertSelect {
aq.modifiers = append(aq.modifiers, modifiers...)
return aq.Select()
}
// AlertGroupBy is the group-by builder for Alert entities. // AlertGroupBy is the group-by builder for Alert entities.
type AlertGroupBy struct { type AlertGroupBy struct {
config config
@ -1197,3 +1213,9 @@ func (as *AlertSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close() defer rows.Close()
return sql.ScanSlice(rows, v) return sql.ScanSlice(rows, v)
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (as *AlertSelect) Modify(modifiers ...func(s *sql.Selector)) *AlertSelect {
as.modifiers = append(as.modifiers, modifiers...)
return as
}

View file

@ -24,6 +24,7 @@ type BouncerQuery struct {
order []OrderFunc order []OrderFunc
fields []string fields []string
predicates []predicate.Bouncer predicates []predicate.Bouncer
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -326,6 +327,9 @@ func (bq *BouncerQuery) sqlAll(ctx context.Context) ([]*Bouncer, error) {
node := nodes[len(nodes)-1] node := nodes[len(nodes)-1]
return node.assignValues(columns, values) return node.assignValues(columns, values)
} }
if len(bq.modifiers) > 0 {
_spec.Modifiers = bq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, bq.driver, _spec); err != nil { if err := sqlgraph.QueryNodes(ctx, bq.driver, _spec); err != nil {
return nil, err return nil, err
} }
@ -337,6 +341,9 @@ func (bq *BouncerQuery) sqlAll(ctx context.Context) ([]*Bouncer, error) {
func (bq *BouncerQuery) sqlCount(ctx context.Context) (int, error) { func (bq *BouncerQuery) sqlCount(ctx context.Context) (int, error) {
_spec := bq.querySpec() _spec := bq.querySpec()
if len(bq.modifiers) > 0 {
_spec.Modifiers = bq.modifiers
}
_spec.Node.Columns = bq.fields _spec.Node.Columns = bq.fields
if len(bq.fields) > 0 { if len(bq.fields) > 0 {
_spec.Unique = bq.unique != nil && *bq.unique _spec.Unique = bq.unique != nil && *bq.unique
@ -415,6 +422,9 @@ func (bq *BouncerQuery) sqlQuery(ctx context.Context) *sql.Selector {
if bq.unique != nil && *bq.unique { if bq.unique != nil && *bq.unique {
selector.Distinct() selector.Distinct()
} }
for _, m := range bq.modifiers {
m(selector)
}
for _, p := range bq.predicates { for _, p := range bq.predicates {
p(selector) p(selector)
} }
@ -432,6 +442,12 @@ func (bq *BouncerQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector return selector
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (bq *BouncerQuery) Modify(modifiers ...func(s *sql.Selector)) *BouncerSelect {
bq.modifiers = append(bq.modifiers, modifiers...)
return bq.Select()
}
// BouncerGroupBy is the group-by builder for Bouncer entities. // BouncerGroupBy is the group-by builder for Bouncer entities.
type BouncerGroupBy struct { type BouncerGroupBy struct {
config config
@ -919,3 +935,9 @@ func (bs *BouncerSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close() defer rows.Close()
return sql.ScanSlice(rows, v) return sql.ScanSlice(rows, v)
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (bs *BouncerSelect) Modify(modifiers ...func(s *sql.Selector)) *BouncerSelect {
bs.modifiers = append(bs.modifiers, modifiers...)
return bs
}

View file

@ -28,6 +28,7 @@ type DecisionQuery struct {
// eager-loading edges. // eager-loading edges.
withOwner *AlertQuery withOwner *AlertQuery
withFKs bool withFKs bool
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -375,6 +376,9 @@ func (dq *DecisionQuery) sqlAll(ctx context.Context) ([]*Decision, error) {
node.Edges.loadedTypes = loadedTypes node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values) return node.assignValues(columns, values)
} }
if len(dq.modifiers) > 0 {
_spec.Modifiers = dq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, dq.driver, _spec); err != nil { if err := sqlgraph.QueryNodes(ctx, dq.driver, _spec); err != nil {
return nil, err return nil, err
} }
@ -416,6 +420,9 @@ func (dq *DecisionQuery) sqlAll(ctx context.Context) ([]*Decision, error) {
func (dq *DecisionQuery) sqlCount(ctx context.Context) (int, error) { func (dq *DecisionQuery) sqlCount(ctx context.Context) (int, error) {
_spec := dq.querySpec() _spec := dq.querySpec()
if len(dq.modifiers) > 0 {
_spec.Modifiers = dq.modifiers
}
_spec.Node.Columns = dq.fields _spec.Node.Columns = dq.fields
if len(dq.fields) > 0 { if len(dq.fields) > 0 {
_spec.Unique = dq.unique != nil && *dq.unique _spec.Unique = dq.unique != nil && *dq.unique
@ -494,6 +501,9 @@ func (dq *DecisionQuery) sqlQuery(ctx context.Context) *sql.Selector {
if dq.unique != nil && *dq.unique { if dq.unique != nil && *dq.unique {
selector.Distinct() selector.Distinct()
} }
for _, m := range dq.modifiers {
m(selector)
}
for _, p := range dq.predicates { for _, p := range dq.predicates {
p(selector) p(selector)
} }
@ -511,6 +521,12 @@ func (dq *DecisionQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector return selector
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (dq *DecisionQuery) Modify(modifiers ...func(s *sql.Selector)) *DecisionSelect {
dq.modifiers = append(dq.modifiers, modifiers...)
return dq.Select()
}
// DecisionGroupBy is the group-by builder for Decision entities. // DecisionGroupBy is the group-by builder for Decision entities.
type DecisionGroupBy struct { type DecisionGroupBy struct {
config config
@ -998,3 +1014,9 @@ func (ds *DecisionSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close() defer rows.Close()
return sql.ScanSlice(rows, v) return sql.ScanSlice(rows, v)
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (ds *DecisionSelect) Modify(modifiers ...func(s *sql.Selector)) *DecisionSelect {
ds.modifiers = append(ds.modifiers, modifiers...)
return ds
}

View file

@ -28,6 +28,7 @@ type EventQuery struct {
// eager-loading edges. // eager-loading edges.
withOwner *AlertQuery withOwner *AlertQuery
withFKs bool withFKs bool
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -375,6 +376,9 @@ func (eq *EventQuery) sqlAll(ctx context.Context) ([]*Event, error) {
node.Edges.loadedTypes = loadedTypes node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values) return node.assignValues(columns, values)
} }
if len(eq.modifiers) > 0 {
_spec.Modifiers = eq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, eq.driver, _spec); err != nil { if err := sqlgraph.QueryNodes(ctx, eq.driver, _spec); err != nil {
return nil, err return nil, err
} }
@ -416,6 +420,9 @@ func (eq *EventQuery) sqlAll(ctx context.Context) ([]*Event, error) {
func (eq *EventQuery) sqlCount(ctx context.Context) (int, error) { func (eq *EventQuery) sqlCount(ctx context.Context) (int, error) {
_spec := eq.querySpec() _spec := eq.querySpec()
if len(eq.modifiers) > 0 {
_spec.Modifiers = eq.modifiers
}
_spec.Node.Columns = eq.fields _spec.Node.Columns = eq.fields
if len(eq.fields) > 0 { if len(eq.fields) > 0 {
_spec.Unique = eq.unique != nil && *eq.unique _spec.Unique = eq.unique != nil && *eq.unique
@ -494,6 +501,9 @@ func (eq *EventQuery) sqlQuery(ctx context.Context) *sql.Selector {
if eq.unique != nil && *eq.unique { if eq.unique != nil && *eq.unique {
selector.Distinct() selector.Distinct()
} }
for _, m := range eq.modifiers {
m(selector)
}
for _, p := range eq.predicates { for _, p := range eq.predicates {
p(selector) p(selector)
} }
@ -511,6 +521,12 @@ func (eq *EventQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector return selector
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (eq *EventQuery) Modify(modifiers ...func(s *sql.Selector)) *EventSelect {
eq.modifiers = append(eq.modifiers, modifiers...)
return eq.Select()
}
// EventGroupBy is the group-by builder for Event entities. // EventGroupBy is the group-by builder for Event entities.
type EventGroupBy struct { type EventGroupBy struct {
config config
@ -998,3 +1014,9 @@ func (es *EventSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close() defer rows.Close()
return sql.ScanSlice(rows, v) return sql.ScanSlice(rows, v)
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (es *EventSelect) Modify(modifiers ...func(s *sql.Selector)) *EventSelect {
es.modifiers = append(es.modifiers, modifiers...)
return es
}

View file

@ -28,6 +28,7 @@ type MachineQuery struct {
predicates []predicate.Machine predicates []predicate.Machine
// eager-loading edges. // eager-loading edges.
withAlerts *AlertQuery withAlerts *AlertQuery
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -368,6 +369,9 @@ func (mq *MachineQuery) sqlAll(ctx context.Context) ([]*Machine, error) {
node.Edges.loadedTypes = loadedTypes node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values) return node.assignValues(columns, values)
} }
if len(mq.modifiers) > 0 {
_spec.Modifiers = mq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, mq.driver, _spec); err != nil { if err := sqlgraph.QueryNodes(ctx, mq.driver, _spec); err != nil {
return nil, err return nil, err
} }
@ -409,6 +413,9 @@ func (mq *MachineQuery) sqlAll(ctx context.Context) ([]*Machine, error) {
func (mq *MachineQuery) sqlCount(ctx context.Context) (int, error) { func (mq *MachineQuery) sqlCount(ctx context.Context) (int, error) {
_spec := mq.querySpec() _spec := mq.querySpec()
if len(mq.modifiers) > 0 {
_spec.Modifiers = mq.modifiers
}
_spec.Node.Columns = mq.fields _spec.Node.Columns = mq.fields
if len(mq.fields) > 0 { if len(mq.fields) > 0 {
_spec.Unique = mq.unique != nil && *mq.unique _spec.Unique = mq.unique != nil && *mq.unique
@ -487,6 +494,9 @@ func (mq *MachineQuery) sqlQuery(ctx context.Context) *sql.Selector {
if mq.unique != nil && *mq.unique { if mq.unique != nil && *mq.unique {
selector.Distinct() selector.Distinct()
} }
for _, m := range mq.modifiers {
m(selector)
}
for _, p := range mq.predicates { for _, p := range mq.predicates {
p(selector) p(selector)
} }
@ -504,6 +514,12 @@ func (mq *MachineQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector return selector
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (mq *MachineQuery) Modify(modifiers ...func(s *sql.Selector)) *MachineSelect {
mq.modifiers = append(mq.modifiers, modifiers...)
return mq.Select()
}
// MachineGroupBy is the group-by builder for Machine entities. // MachineGroupBy is the group-by builder for Machine entities.
type MachineGroupBy struct { type MachineGroupBy struct {
config config
@ -991,3 +1007,9 @@ func (ms *MachineSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close() defer rows.Close()
return sql.ScanSlice(rows, v) return sql.ScanSlice(rows, v)
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (ms *MachineSelect) Modify(modifiers ...func(s *sql.Selector)) *MachineSelect {
ms.modifiers = append(ms.modifiers, modifiers...)
return ms
}

View file

@ -28,6 +28,7 @@ type MetaQuery struct {
// eager-loading edges. // eager-loading edges.
withOwner *AlertQuery withOwner *AlertQuery
withFKs bool withFKs bool
modifiers []func(s *sql.Selector)
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -375,6 +376,9 @@ func (mq *MetaQuery) sqlAll(ctx context.Context) ([]*Meta, error) {
node.Edges.loadedTypes = loadedTypes node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values) return node.assignValues(columns, values)
} }
if len(mq.modifiers) > 0 {
_spec.Modifiers = mq.modifiers
}
if err := sqlgraph.QueryNodes(ctx, mq.driver, _spec); err != nil { if err := sqlgraph.QueryNodes(ctx, mq.driver, _spec); err != nil {
return nil, err return nil, err
} }
@ -416,6 +420,9 @@ func (mq *MetaQuery) sqlAll(ctx context.Context) ([]*Meta, error) {
func (mq *MetaQuery) sqlCount(ctx context.Context) (int, error) { func (mq *MetaQuery) sqlCount(ctx context.Context) (int, error) {
_spec := mq.querySpec() _spec := mq.querySpec()
if len(mq.modifiers) > 0 {
_spec.Modifiers = mq.modifiers
}
_spec.Node.Columns = mq.fields _spec.Node.Columns = mq.fields
if len(mq.fields) > 0 { if len(mq.fields) > 0 {
_spec.Unique = mq.unique != nil && *mq.unique _spec.Unique = mq.unique != nil && *mq.unique
@ -494,6 +501,9 @@ func (mq *MetaQuery) sqlQuery(ctx context.Context) *sql.Selector {
if mq.unique != nil && *mq.unique { if mq.unique != nil && *mq.unique {
selector.Distinct() selector.Distinct()
} }
for _, m := range mq.modifiers {
m(selector)
}
for _, p := range mq.predicates { for _, p := range mq.predicates {
p(selector) p(selector)
} }
@ -511,6 +521,12 @@ func (mq *MetaQuery) sqlQuery(ctx context.Context) *sql.Selector {
return selector return selector
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (mq *MetaQuery) Modify(modifiers ...func(s *sql.Selector)) *MetaSelect {
mq.modifiers = append(mq.modifiers, modifiers...)
return mq.Select()
}
// MetaGroupBy is the group-by builder for Meta entities. // MetaGroupBy is the group-by builder for Meta entities.
type MetaGroupBy struct { type MetaGroupBy struct {
config config
@ -998,3 +1014,9 @@ func (ms *MetaSelect) sqlScan(ctx context.Context, v interface{}) error {
defer rows.Close() defer rows.Close()
return sql.ScanSlice(rows, v) return sql.ScanSlice(rows, v)
} }
// Modify adds a query modifier for attaching custom logic to queries.
func (ms *MetaSelect) Modify(modifiers ...func(s *sql.Selector)) *MetaSelect {
ms.modifiers = append(ms.modifiers, modifiers...)
return ms
}