13 Commits

Author SHA1 Message Date
Nikita Tokarchuk 87708fee04 Add callback support to a saving 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk 06f6f48f11 Add context support to a saving 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk 28be1f46b9 Add filters support for a saving 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk 848703d56d Add callback support to a single deleting 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk 8fcd764a8c Add context query support to a single deleting 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk 50e947b203 Invoke onclose at the end of an array deleting 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk 73dc4974a2 Add query context support for an array deleting 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk 08397650c6 Add filters support for an array deleting 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk ee4bf46662 Add callback support for a counting 2020-07-23 01:44:22 +02:00
Nikita Tokarchuk 9fb3094b87 Use reflect2 2020-07-23 00:00:53 +02:00
Nikita Tokarchuk b22b0f0919 Add query to the context 2020-07-23 00:00:53 +02:00
Nikita Tokarchuk 951e5f5bef Add onclose callback 2020-07-23 00:00:53 +02:00
Nikita Tokarchuk b796d5ac3b Make callback type 2020-07-23 00:00:53 +02:00
19 changed files with 133 additions and 104 deletions
+2
View File
@@ -3,6 +3,8 @@ module github.com/mainnika/mongox-go-driver/v2
require ( require (
github.com/google/go-cmp v0.3.0 // indirect github.com/google/go-cmp v0.3.0 // indirect
github.com/klauspost/compress v1.10.1 // indirect github.com/klauspost/compress v1.10.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/stretchr/testify v1.5.1 github.com/stretchr/testify v1.5.1
github.com/xdg/stringprep v1.0.0 // indirect github.com/xdg/stringprep v1.0.0 // indirect
+7
View File
@@ -44,11 +44,17 @@ github.com/klauspost/compress v1.10.1 h1:a/QY0o9S6wCi0XhxaMX/QmusicNUqCqFugR6WKP
github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -113,6 +119,7 @@ golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+2 -2
View File
@@ -3,10 +3,10 @@ package base
import ( import (
"fmt" "fmt"
"github.com/modern-go/reflect2"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"github.com/mainnika/mongox-go-driver/v2/mongox" "github.com/mainnika/mongox-go-driver/v2/mongox"
"github.com/mainnika/mongox-go-driver/v2/mongox/utils"
) )
// GetID returns source document id // GetID returns source document id
@@ -63,7 +63,7 @@ func getObjectOrPanic(source mongox.JSONBased) (id primitive.D) {
func getInterfaceOrPanic(source mongox.InterfaceBased) (id interface{}) { func getInterfaceOrPanic(source mongox.InterfaceBased) (id interface{}) {
id = source.GetID() id = source.GetID()
if !utils.IsNil(id) { if !reflect2.IsNil(id) {
return id return id
} }
-19
View File
@@ -1,19 +0,0 @@
package database
import (
"context"
"github.com/mainnika/mongox-go-driver/v2/mongox/query"
)
func onDecode(ctx context.Context, iter interface{}, callbacks ...query.OnDecode) (err error) {
for _, cb := range callbacks {
err = cb(ctx, iter)
if err != nil {
return
}
}
return
}
+4 -1
View File
@@ -13,11 +13,14 @@ func (d *Database) Count(target interface{}, filters ...interface{}) (result int
collection := d.GetCollectionOf(target) collection := d.GetCollectionOf(target)
opts := options.Count() opts := options.Count()
composed := query.Compose(filters...) composed := query.Compose(filters...)
ctx := query.WithContext(d.Context(), composed)
opts.Limit = composed.Limiter() opts.Limit = composed.Limiter()
opts.Skip = composed.Skipper() opts.Skip = composed.Skipper()
result, err = collection.CountDocuments(d.Context(), composed.M(), opts) result, err = collection.CountDocuments(ctx, composed.M(), opts)
_ = composed.OnClose().Invoke(ctx, target)
return return
} }
+9 -2
View File
@@ -8,10 +8,11 @@ import (
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"github.com/mainnika/mongox-go-driver/v2/mongox/base" "github.com/mainnika/mongox-go-driver/v2/mongox/base"
"github.com/mainnika/mongox-go-driver/v2/mongox/query"
) )
// DeleteArray removes documents list from a database by their ids // DeleteArray removes documents list from a database by their ids
func (d *Database) DeleteArray(target interface{}) (err error) { func (d *Database) DeleteArray(target interface{}, filters ...interface{}) (err error) {
targetV := reflect.ValueOf(target) targetV := reflect.ValueOf(target)
targetT := targetV.Type() targetT := targetV.Type()
@@ -37,6 +38,8 @@ func (d *Database) DeleteArray(target interface{}) (err error) {
collection := d.GetCollectionOf(zeroElem.Interface()) collection := d.GetCollectionOf(zeroElem.Interface())
opts := options.Delete() opts := options.Delete()
ids := primitive.A{} ids := primitive.A{}
composed := query.Compose(filters...)
ctx := query.WithContext(d.Context(), composed)
for i := 0; i < targetLen; i++ { for i := 0; i < targetLen; i++ {
elem := targetSliceV.Index(i) elem := targetSliceV.Index(i)
@@ -47,7 +50,11 @@ func (d *Database) DeleteArray(target interface{}) (err error) {
return fmt.Errorf("can't delete zero elements") return fmt.Errorf("can't delete zero elements")
} }
result, err := collection.DeleteMany(d.Context(), primitive.M{"_id": primitive.M{"$in": ids}}, opts) composed.And(primitive.M{"_id": primitive.M{"$in": ids}})
defer composed.OnClose().Invoke(ctx, target)
result, err := collection.DeleteMany(ctx, composed.M(), opts)
if err != nil { if err != nil {
return return
} }
+14 -3
View File
@@ -4,12 +4,12 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/modern-go/reflect2"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"github.com/mainnika/mongox-go-driver/v2/mongox/base" "github.com/mainnika/mongox-go-driver/v2/mongox/base"
"github.com/mainnika/mongox-go-driver/v2/mongox/query" "github.com/mainnika/mongox-go-driver/v2/mongox/query"
"github.com/mainnika/mongox-go-driver/v2/mongox/utils"
) )
// DeleteOne removes a document from a database and then returns it into target // DeleteOne removes a document from a database and then returns it into target
@@ -19,10 +19,11 @@ func (d *Database) DeleteOne(target interface{}, filters ...interface{}) (err er
opts := &options.FindOneAndDeleteOptions{} opts := &options.FindOneAndDeleteOptions{}
composed := query.Compose(filters...) composed := query.Compose(filters...)
protected := base.GetProtection(target) protected := base.GetProtection(target)
ctx := query.WithContext(d.Context(), composed)
opts.Sort = composed.Sorter() opts.Sort = composed.Sorter()
if !utils.IsNil(target) { if !reflect2.IsNil(target) {
composed.And(primitive.M{"_id": base.GetID(target)}) composed.And(primitive.M{"_id": base.GetID(target)})
} }
@@ -32,12 +33,22 @@ func (d *Database) DeleteOne(target interface{}, filters ...interface{}) (err er
protected.V = time.Now().Unix() protected.V = time.Now().Unix()
} }
result := collection.FindOneAndDelete(d.Context(), composed.M(), opts) defer composed.OnClose().Invoke(ctx, target)
result := collection.FindOneAndDelete(ctx, composed.M(), opts)
if result.Err() != nil { if result.Err() != nil {
return fmt.Errorf("can't create find one and delete result: %w", result.Err()) return fmt.Errorf("can't create find one and delete result: %w", result.Err())
} }
err = result.Decode(target) err = result.Decode(target)
if err != nil {
return
}
err = composed.OnDecode().Invoke(ctx, target)
if err != nil {
return
}
return return
} }
+8 -5
View File
@@ -34,6 +34,7 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
composed := query.Compose(filters...) composed := query.Compose(filters...)
zeroElem := reflect.Zero(targetSliceElemT) zeroElem := reflect.Zero(targetSliceElemT)
hasPreloader, _ := composed.Preloader() hasPreloader, _ := composed.Preloader()
ctx := query.WithContext(d.Context(), composed)
var result *mongox.Cursor var result *mongox.Cursor
var i int var i int
@@ -48,7 +49,9 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
return return
} }
for i = 0; result.Next(d.Context()); { defer composed.OnClose().Invoke(ctx, target)
for i = 0; result.Next(ctx); {
var elem interface{} var elem interface{}
@@ -65,13 +68,13 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
err = result.Decode(elem) err = result.Decode(elem)
} }
if err != nil { if err != nil {
_ = result.Close(d.Context()) _ = result.Close(ctx)
return return
} }
err = onDecode(d.ctx, elem, composed.OnDecode()...) err = composed.OnDecode().Invoke(ctx, elem)
if err != nil { if err != nil {
_ = result.Close(d.Context()) _ = result.Close(ctx)
return return
} }
@@ -81,5 +84,5 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
targetSliceV = targetSliceV.Slice(0, i) targetSliceV = targetSliceV.Slice(0, i)
targetV.Elem().Set(targetSliceV) targetV.Elem().Set(targetSliceV)
return result.Close(d.Context()) return result.Close(ctx)
} }
+5 -2
View File
@@ -13,6 +13,7 @@ func (d *Database) LoadOne(target interface{}, filters ...interface{}) (err erro
composed := query.Compose(append(filters, query.Limit(1))...) composed := query.Compose(append(filters, query.Limit(1))...)
hasPreloader, _ := composed.Preloader() hasPreloader, _ := composed.Preloader()
ctx := query.WithContext(d.Context(), composed)
var result *mongox.Cursor var result *mongox.Cursor
@@ -25,7 +26,9 @@ func (d *Database) LoadOne(target interface{}, filters ...interface{}) (err erro
return fmt.Errorf("can't create find result: %w", err) return fmt.Errorf("can't create find result: %w", err)
} }
hasNext := result.Next(d.Context()) defer composed.OnClose().Invoke(ctx, target)
hasNext := result.Next(ctx)
if result.Err() != nil { if result.Err() != nil {
return err return err
} }
@@ -40,7 +43,7 @@ func (d *Database) LoadOne(target interface{}, filters ...interface{}) (err erro
return return
} }
err = onDecode(d.ctx, target, composed.OnDecode()...) err = composed.OnDecode().Invoke(ctx, target)
if err != nil { if err != nil {
return return
} }
+2 -1
View File
@@ -14,6 +14,7 @@ func (d *Database) LoadStream(target interface{}, filters ...interface{}) (loade
composed := query.Compose(filters...) composed := query.Compose(filters...)
hasPreloader, _ := composed.Preloader() hasPreloader, _ := composed.Preloader()
ctx := query.WithContext(d.Context(), composed)
if hasPreloader { if hasPreloader {
cursor, err = d.createAggregateLoad(target, composed) cursor, err = d.createAggregateLoad(target, composed)
@@ -25,7 +26,7 @@ func (d *Database) LoadStream(target interface{}, filters ...interface{}) (loade
return return
} }
loader = &StreamLoader{cur: cursor, ctx: d.Context(), target: target, query: composed} loader = &StreamLoader{cur: cursor, ctx: ctx, target: target, query: composed}
return return
} }
+19 -4
View File
@@ -12,13 +12,16 @@ import (
) )
// SaveOne saves a single source document to the database // SaveOne saves a single source document to the database
func (d *Database) SaveOne(source interface{}) (err error) { func (d *Database) SaveOne(source interface{}, filters ...interface{}) (err error) {
collection := d.GetCollectionOf(source) collection := d.GetCollectionOf(source)
opts := options.FindOneAndReplace() opts := options.FindOneAndReplace()
id := base.GetID(source) id := base.GetID(source)
protected := base.GetProtection(source) protected := base.GetProtection(source)
composed := query.Compose(bson.M{"_id": id}) composed := query.Compose(filters...)
ctx := query.WithContext(d.Context(), composed)
composed.And(bson.M{"_id": id})
opts.SetUpsert(true) opts.SetUpsert(true)
opts.SetReturnDocument(options.After) opts.SetReturnDocument(options.After)
@@ -29,10 +32,22 @@ func (d *Database) SaveOne(source interface{}) (err error) {
protected.V = time.Now().Unix() protected.V = time.Now().Unix()
} }
result := collection.FindOneAndReplace(d.Context(), composed.M(), source, opts) defer composed.OnClose().Invoke(ctx, source)
result := collection.FindOneAndReplace(ctx, composed.M(), source, opts)
if result.Err() != nil { if result.Err() != nil {
return result.Err() return result.Err()
} }
return result.Decode(source) err = result.Decode(source)
if err != nil {
return
}
err = composed.OnDecode().Invoke(ctx, source)
if err != nil {
return
}
return
} }
+4 -1
View File
@@ -42,7 +42,7 @@ func (l *StreamLoader) Decode() (err error) {
return return
} }
err = onDecode(l.ctx, l.target, l.query.OnDecode()...) err = l.query.OnDecode().Invoke(l.ctx, l.target)
if err != nil { if err != nil {
return return
} }
@@ -72,6 +72,9 @@ func (l *StreamLoader) Cursor() (cursor *mongox.Cursor) {
// Close cursor // Close cursor
func (l *StreamLoader) Close() (err error) { func (l *StreamLoader) Close() (err error) {
_ = l.query.OnClose().Invoke(l.ctx, l.target)
return l.cur.Close(l.ctx) return l.cur.Close(l.ctx)
} }
+2 -2
View File
@@ -22,12 +22,12 @@ type Database interface {
New(ctx context.Context) (db Database) New(ctx context.Context) (db Database)
GetCollectionOf(document interface{}) (collection *Collection) GetCollectionOf(document interface{}) (collection *Collection)
Count(target interface{}, filters ...interface{}) (count int64, err error) Count(target interface{}, filters ...interface{}) (count int64, err error)
DeleteArray(target interface{}) (err error) DeleteArray(target interface{}, filters ...interface{}) (err error)
DeleteOne(target interface{}, filters ...interface{}) (err error) DeleteOne(target interface{}, filters ...interface{}) (err error)
LoadArray(target interface{}, filters ...interface{}) (err error) LoadArray(target interface{}, filters ...interface{}) (err error)
LoadOne(target interface{}, filters ...interface{}) (err error) LoadOne(target interface{}, filters ...interface{}) (err error)
LoadStream(target interface{}, filters ...interface{}) (loader StreamLoader, err error) LoadStream(target interface{}, filters ...interface{}) (loader StreamLoader, err error)
SaveOne(source interface{}) (err error) SaveOne(source interface{}, filters ...interface{}) (err error)
IndexEnsure(cfg interface{}, document interface{}) (err error) IndexEnsure(cfg interface{}, document interface{}) (err error)
} }
+20 -1
View File
@@ -4,4 +4,23 @@ import (
"context" "context"
) )
type OnDecode func(ctx context.Context, iter interface{}) (err error) type Callback func(ctx context.Context, iter interface{}) (err error)
type Callbacks []Callback
type (
OnDecode Callback
OnClose Callback
)
// Invoke callbacks sequence
func (c Callbacks) Invoke(ctx context.Context, iter interface{}) (err error) {
for _, cb := range c {
err = cb(ctx, iter)
if err != nil {
return
}
}
return
}
+9 -4
View File
@@ -3,11 +3,11 @@ package query
import ( import (
"fmt" "fmt"
"github.com/modern-go/reflect2"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"github.com/mainnika/mongox-go-driver/v2/mongox/base/protection" "github.com/mainnika/mongox-go-driver/v2/mongox/base/protection"
"github.com/mainnika/mongox-go-driver/v2/mongox/utils"
) )
// Compose is a function to compose filters into a single query // Compose is a function to compose filters into a single query
@@ -27,7 +27,7 @@ func Compose(filters ...interface{}) (query *Query) {
// Push applies single filter to a query // Push applies single filter to a query
func Push(q *Query, f interface{}) (ok bool) { func Push(q *Query, f interface{}) (ok bool) {
if utils.IsNil(f) { if reflect2.IsNil(f) {
return true return true
} }
@@ -129,9 +129,14 @@ func applyCallbacks(q *Query, f interface{}) (ok bool) {
switch cb := f.(type) { switch cb := f.(type) {
case OnDecode: case OnDecode:
q.ondecode = append(q.ondecode, cb) q.ondecode = append(q.ondecode, Callback(cb))
ok = true case OnClose:
q.onclose = append(q.onclose, Callback(cb))
default:
return
} }
ok = true
return return
} }
+19
View File
@@ -0,0 +1,19 @@
package query
import (
"context"
)
type ctxQueryKey struct{}
// GetFromContext function extracts the request data from context
func GetFromContext(ctx context.Context) (q *Query, ok bool) {
q, ok = ctx.Value(ctxQueryKey{}).(*Query)
return
}
// WithContext function creates the new context with request data
func WithContext(ctx context.Context, q *Query) (withQuery context.Context) {
withQuery = context.WithValue(ctx, ctxQueryKey{}, q)
return
}
+7 -2
View File
@@ -11,7 +11,8 @@ type Query struct {
sorter Sorter sorter Sorter
skipper Skipper skipper Skipper
preloader Preloader preloader Preloader
ondecode []OnDecode ondecode Callbacks
onclose Callbacks
} }
// And function pushes the elem query to the $and array of the query // And function pushes the elem query to the $and array of the query
@@ -77,10 +78,14 @@ func (q *Query) Preloader() (ok bool, preloads []string) {
} }
// OnDecode callback is called after the mongo decode function // OnDecode callback is called after the mongo decode function
func (q *Query) OnDecode() (callbacks []OnDecode) { func (q *Query) OnDecode() (callbacks Callbacks) {
return q.ondecode return q.ondecode
} }
func (q *Query) OnClose() (callbacks Callbacks) {
return q.onclose
}
// Empty checks the query for any content // Empty checks the query for any content
func (q *Query) Empty() (isEmpty bool) { func (q *Query) Empty() (isEmpty bool) {
return len(q.m) == 0 return len(q.m) == 0
-23
View File
@@ -1,23 +0,0 @@
package utils
import (
"unsafe"
)
// IsNil function evaluates the interface value to nil
func IsNil(i interface{}) (isNil bool) {
type iface struct {
_ unsafe.Pointer
ptr unsafe.Pointer
}
unpacked := (*iface)(unsafe.Pointer(&i))
if unpacked.ptr == nil {
isNil = true
return
}
isNil = *(*unsafe.Pointer)(unpacked.ptr) == nil
return
}
-32
View File
@@ -1,32 +0,0 @@
package utils
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsNil(t *testing.T) {
testvalues := []struct {
i interface{}
isnil bool
}{
{nil, true},
{(*string)(nil), true},
{([]string)(nil), true},
{(map[string]string)(nil), true},
{(func() bool)(nil), true},
{(chan func() bool)(nil), true},
{"", true},
{0, true},
{append(([]string)(nil), ""), false},
{[]string{}, false},
{1, false},
{"1", false},
}
for _, tt := range testvalues {
assert.Equal(t, tt.isnil, IsNil(tt.i))
}
}