| OLD | NEW |
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package txnBuf | 5 package txnBuf |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "fmt" | 9 "fmt" |
| 10 "math/rand" | 10 "math/rand" |
| 11 "testing" | 11 "testing" |
| 12 | 12 |
| 13 "github.com/luci/gae/filter/count" | 13 "github.com/luci/gae/filter/count" |
| 14 "github.com/luci/gae/impl/memory" | 14 "github.com/luci/gae/impl/memory" |
| 15 » "github.com/luci/gae/service/datastore" | 15 » ds "github.com/luci/gae/service/datastore" |
| 16 |
| 16 "github.com/luci/luci-go/common/data/cmpbin" | 17 "github.com/luci/luci-go/common/data/cmpbin" |
| 17 "github.com/luci/luci-go/common/errors" | 18 "github.com/luci/luci-go/common/errors" |
| 19 |
| 20 "golang.org/x/net/context" |
| 21 |
| 18 . "github.com/luci/luci-go/common/testing/assertions" | 22 . "github.com/luci/luci-go/common/testing/assertions" |
| 19 . "github.com/smartystreets/goconvey/convey" | 23 . "github.com/smartystreets/goconvey/convey" |
| 20 "golang.org/x/net/context" | |
| 21 ) | 24 ) |
| 22 | 25 |
| 23 type Foo struct { | 26 type Foo struct { |
| 24 » ID int64 `gae:"$id"` | 27 » ID int64 `gae:"$id"` |
| 25 » Parent *datastore.Key `gae:"$parent"` | 28 » Parent *ds.Key `gae:"$parent"` |
| 26 | 29 |
| 27 Value []int64 | 30 Value []int64 |
| 28 ValueNI []byte `gae:",noindex"` | 31 ValueNI []byte `gae:",noindex"` |
| 29 Sort []string | 32 Sort []string |
| 30 } | 33 } |
| 31 | 34 |
| 32 func toIntSlice(stuff []interface{}) []int64 { | 35 func toIntSlice(stuff []interface{}) []int64 { |
| 33 vals, ok := stuff[0].([]int64) | 36 vals, ok := stuff[0].([]int64) |
| 34 if !ok { | 37 if !ok { |
| 35 vals = make([]int64, len(stuff)) | 38 vals = make([]int64, len(stuff)) |
| 36 for i := range vals { | 39 for i := range vals { |
| 37 vals[i] = int64(stuff[i].(int)) | 40 vals[i] = int64(stuff[i].(int)) |
| 38 } | 41 } |
| 39 } | 42 } |
| 40 return vals | 43 return vals |
| 41 } | 44 } |
| 42 | 45 |
| 43 func toInt64(thing interface{}) int64 { | 46 func toInt64(thing interface{}) int64 { |
| 44 switch x := thing.(type) { | 47 switch x := thing.(type) { |
| 45 case int: | 48 case int: |
| 46 return int64(x) | 49 return int64(x) |
| 47 case int64: | 50 case int64: |
| 48 return x | 51 return x |
| 49 default: | 52 default: |
| 50 panic(fmt.Errorf("wat r it? %v", x)) | 53 panic(fmt.Errorf("wat r it? %v", x)) |
| 51 } | 54 } |
| 52 } | 55 } |
| 53 | 56 |
| 54 func fooShouldHave(ds datastore.Interface) func(interface{}, ...interface{}) str
ing { | 57 func fooShouldHave(c context.Context) func(interface{}, ...interface{}) string { |
| 55 return func(id interface{}, values ...interface{}) string { | 58 return func(id interface{}, values ...interface{}) string { |
| 56 f := &Foo{ID: toInt64(id)} | 59 f := &Foo{ID: toInt64(id)} |
| 57 » » err := ds.Get(f) | 60 » » err := ds.Get(c, f) |
| 58 if len(values) == 0 { | 61 if len(values) == 0 { |
| 59 » » » return ShouldEqual(err, datastore.ErrNoSuchEntity) | 62 » » » return ShouldEqual(err, ds.ErrNoSuchEntity) |
| 60 } | 63 } |
| 61 | 64 |
| 62 ret := ShouldBeNil(err) | 65 ret := ShouldBeNil(err) |
| 63 if ret == "" { | 66 if ret == "" { |
| 64 if data, ok := values[0].([]byte); ok { | 67 if data, ok := values[0].([]byte); ok { |
| 65 ret = ShouldResemble(f.ValueNI, data) | 68 ret = ShouldResemble(f.ValueNI, data) |
| 66 } else { | 69 } else { |
| 67 ret = ShouldResemble(f.Value, toIntSlice(values)
) | 70 ret = ShouldResemble(f.Value, toIntSlice(values)
) |
| 68 } | 71 } |
| 69 } | 72 } |
| 70 return ret | 73 return ret |
| 71 } | 74 } |
| 72 } | 75 } |
| 73 | 76 |
| 74 func fooSetTo(ds datastore.Interface) func(interface{}, ...interface{}) string { | 77 func fooSetTo(c context.Context) func(interface{}, ...interface{}) string { |
| 75 return func(id interface{}, values ...interface{}) string { | 78 return func(id interface{}, values ...interface{}) string { |
| 76 f := &Foo{ID: toInt64(id)} | 79 f := &Foo{ID: toInt64(id)} |
| 77 if len(values) == 0 { | 80 if len(values) == 0 { |
| 78 » » » return ShouldBeNil(ds.Delete(ds.KeyForObj(f))) | 81 » » » return ShouldBeNil(ds.Delete(c, ds.KeyForObj(c, f))) |
| 79 } | 82 } |
| 80 if data, ok := values[0].([]byte); ok { | 83 if data, ok := values[0].([]byte); ok { |
| 81 f.ValueNI = data | 84 f.ValueNI = data |
| 82 } else { | 85 } else { |
| 83 f.Value = toIntSlice(values) | 86 f.Value = toIntSlice(values) |
| 84 } | 87 } |
| 85 » » return ShouldBeNil(ds.Put(f)) | 88 » » return ShouldBeNil(ds.Put(c, f)) |
| 86 } | 89 } |
| 87 } | 90 } |
| 88 | 91 |
| 89 var ( | 92 var ( |
| 90 dataMultiRoot = make([]*Foo, 20) | 93 dataMultiRoot = make([]*Foo, 20) |
| 91 dataSingleRoot = make([]*Foo, 20) | 94 dataSingleRoot = make([]*Foo, 20) |
| 92 hugeField = make([]byte, DefaultSizeBudget/8) | 95 hugeField = make([]byte, DefaultSizeBudget/8) |
| 93 hugeData = make([]*Foo, 11) | 96 hugeData = make([]*Foo, 11) |
| 94 » root = datastore.MakeKey("something~else", "", "Parent", 1) | 97 » root = ds.KeyContext{"something~else", ""}.MakeKey("Parent", 1
) |
| 95 ) | 98 ) |
| 96 | 99 |
| 97 func init() { | 100 func init() { |
| 98 cb := func(i int64) string { | 101 cb := func(i int64) string { |
| 99 buf := &bytes.Buffer{} | 102 buf := &bytes.Buffer{} |
| 100 cmpbin.WriteInt(buf, i) | 103 cmpbin.WriteInt(buf, i) |
| 101 return buf.String() | 104 return buf.String() |
| 102 } | 105 } |
| 103 | 106 |
| 104 rs := rand.NewSource(0) | 107 rs := rand.NewSource(0) |
| 105 root := datastore.MakeKey("something~else", "", "Parent", 1) | |
| 106 nums := make([]string, 20) | 108 nums := make([]string, 20) |
| 107 for i := range dataMultiRoot { | 109 for i := range dataMultiRoot { |
| 108 id := int64(i + 1) | 110 id := int64(i + 1) |
| 109 nums[i] = cb(id) | 111 nums[i] = cb(id) |
| 110 | 112 |
| 111 val := make([]int64, rs.Int63()%20) | 113 val := make([]int64, rs.Int63()%20) |
| 112 for j := range val { | 114 for j := range val { |
| 113 r := rs.Int63() | 115 r := rs.Int63() |
| 114 val[j] = r | 116 val[j] = r |
| 115 } | 117 } |
| 116 | 118 |
| 117 dataMultiRoot[i] = &Foo{ID: id, Value: val} | 119 dataMultiRoot[i] = &Foo{ID: id, Value: val} |
| 118 dataSingleRoot[i] = &Foo{ID: id, Parent: root, Value: val} | 120 dataSingleRoot[i] = &Foo{ID: id, Parent: root, Value: val} |
| 119 } | 121 } |
| 120 | 122 |
| 121 for i := range hugeField { | 123 for i := range hugeField { |
| 122 hugeField[i] = byte(i) | 124 hugeField[i] = byte(i) |
| 123 } | 125 } |
| 124 | 126 |
| 125 for i := range hugeData { | 127 for i := range hugeData { |
| 126 hugeData[i] = &Foo{ID: int64(i + 1), ValueNI: hugeField} | 128 hugeData[i] = &Foo{ID: int64(i + 1), ValueNI: hugeField} |
| 127 } | 129 } |
| 128 } | 130 } |
| 129 | 131 |
| 130 func mkds(data []*Foo) (under, over *count.DSCounter, ds datastore.Interface) { | 132 func mkds(data []*Foo) (under, over *count.DSCounter, c context.Context) { |
| 131 » c := memory.UseWithAppID(context.Background(), "something~else") | 133 » c = memory.UseWithAppID(context.Background(), "something~else") |
| 132 » ds = datastore.Get(c) | |
| 133 | 134 |
| 134 » dataKey := ds.KeyForObj(data[0]) | 135 » dataKey := ds.KeyForObj(c, data[0]) |
| 135 » if err := ds.AllocateIDs(ds.NewIncompleteKeys(100, dataKey.Kind(), dataK
ey.Parent())); err != nil { | 136 » if err := ds.AllocateIDs(c, ds.NewIncompleteKeys(c, 100, dataKey.Kind(),
dataKey.Parent())); err != nil { |
| 136 panic(err) | 137 panic(err) |
| 137 } | 138 } |
| 138 » if err := ds.PutMulti(data); err != nil { | 139 » if err := ds.Put(c, data); err != nil { |
| 139 panic(err) | 140 panic(err) |
| 140 } | 141 } |
| 141 | 142 |
| 142 c, under = count.FilterRDS(c) | 143 c, under = count.FilterRDS(c) |
| 143 c = FilterRDS(c) | 144 c = FilterRDS(c) |
| 144 c, over = count.FilterRDS(c) | 145 c, over = count.FilterRDS(c) |
| 145 ds = datastore.Get(c) | |
| 146 return | 146 return |
| 147 } | 147 } |
| 148 | 148 |
| 149 func TestTransactionBuffers(t *testing.T) { | 149 func TestTransactionBuffers(t *testing.T) { |
| 150 t.Parallel() | 150 t.Parallel() |
| 151 | 151 |
| 152 Convey("Get/Put/Delete", t, func() { | 152 Convey("Get/Put/Delete", t, func() { |
| 153 » » under, over, ds := mkds(dataMultiRoot) | 153 » » under, over, c := mkds(dataMultiRoot) |
| 154 » » ds.Testable().SetTransactionRetryCount(1) | 154 » » ds.GetTestable(c).SetTransactionRetryCount(1) |
| 155 | 155 |
| 156 So(under.PutMulti.Total(), ShouldEqual, 0) | 156 So(under.PutMulti.Total(), ShouldEqual, 0) |
| 157 So(over.PutMulti.Total(), ShouldEqual, 0) | 157 So(over.PutMulti.Total(), ShouldEqual, 0) |
| 158 | 158 |
| 159 Convey("Good", func() { | 159 Convey("Good", func() { |
| 160 Convey("read-only", func() { | 160 Convey("read-only", func() { |
| 161 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 161 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 162 » » » » » ds := datastore.Get(c) | 162 » » » » » So(4, fooShouldHave(c), dataMultiRoot[3]
.Value) |
| 163 | |
| 164 » » » » » So(4, fooShouldHave(ds), dataMultiRoot[3
].Value) | |
| 165 return nil | 163 return nil |
| 166 }, nil), ShouldBeNil) | 164 }, nil), ShouldBeNil) |
| 167 }) | 165 }) |
| 168 | 166 |
| 169 Convey("single-level read/write", func() { | 167 Convey("single-level read/write", func() { |
| 170 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 168 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 171 » » » » » ds := datastore.Get(c) | 169 » » » » » So(4, fooShouldHave(c), dataMultiRoot[3]
.Value) |
| 172 | 170 |
| 173 » » » » » So(4, fooShouldHave(ds), dataMultiRoot[3
].Value) | 171 » » » » » So(4, fooSetTo(c), 1, 2, 3, 4) |
| 174 | 172 |
| 175 » » » » » So(4, fooSetTo(ds), 1, 2, 3, 4) | 173 » » » » » So(3, fooSetTo(c), 1, 2, 3, 4) |
| 176 | |
| 177 » » » » » So(3, fooSetTo(ds), 1, 2, 3, 4) | |
| 178 | 174 |
| 179 // look! it remembers :) | 175 // look! it remembers :) |
| 180 » » » » » So(4, fooShouldHave(ds), 1, 2, 3, 4) | 176 » » » » » So(4, fooShouldHave(c), 1, 2, 3, 4) |
| 181 return nil | 177 return nil |
| 182 » » » » }, &datastore.TransactionOptions{XG: true}), Sho
uldBeNil) | 178 » » » » }, &ds.TransactionOptions{XG: true}), ShouldBeNi
l) |
| 183 | 179 |
| 184 // 2 because we are simulating a transaction fai
lure | 180 // 2 because we are simulating a transaction fai
lure |
| 185 So(under.PutMulti.Total(), ShouldEqual, 2) | 181 So(under.PutMulti.Total(), ShouldEqual, 2) |
| 186 | 182 |
| 187 » » » » So(3, fooShouldHave(ds), 1, 2, 3, 4) | 183 » » » » So(3, fooShouldHave(c), 1, 2, 3, 4) |
| 188 » » » » So(4, fooShouldHave(ds), 1, 2, 3, 4) | 184 » » » » So(4, fooShouldHave(c), 1, 2, 3, 4) |
| 189 }) | 185 }) |
| 190 | 186 |
| 191 Convey("multi-level read/write", func() { | 187 Convey("multi-level read/write", func() { |
| 192 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 188 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 193 » » » » » ds := datastore.Get(c) | 189 » » » » » So(3, fooShouldHave(c), dataMultiRoot[2]
.Value) |
| 194 | 190 |
| 195 » » » » » So(3, fooShouldHave(ds), dataMultiRoot[2
].Value) | 191 » » » » » So(3, fooSetTo(c), 1, 2, 3, 4) |
| 196 | 192 » » » » » So(7, fooSetTo(c)) |
| 197 » » » » » So(3, fooSetTo(ds), 1, 2, 3, 4) | |
| 198 » » » » » So(7, fooSetTo(ds)) | |
| 199 | 193 |
| 200 vals := []*Foo{ | 194 vals := []*Foo{ |
| 201 {ID: 793}, | 195 {ID: 793}, |
| 202 {ID: 7}, | 196 {ID: 7}, |
| 203 {ID: 3}, | 197 {ID: 3}, |
| 204 {ID: 4}, | 198 {ID: 4}, |
| 205 } | 199 } |
| 206 » » » » » So(ds.GetMulti(vals), ShouldResemble, er
rors.NewMultiError( | 200 » » » » » So(ds.Get(c, vals), ShouldResemble, erro
rs.NewMultiError( |
| 207 » » » » » » datastore.ErrNoSuchEntity, | 201 » » » » » » ds.ErrNoSuchEntity, |
| 208 » » » » » » datastore.ErrNoSuchEntity, | 202 » » » » » » ds.ErrNoSuchEntity, |
| 209 nil, | 203 nil, |
| 210 nil, | 204 nil, |
| 211 )) | 205 )) |
| 212 | 206 |
| 213 So(vals[0].Value, ShouldBeNil) | 207 So(vals[0].Value, ShouldBeNil) |
| 214 So(vals[1].Value, ShouldBeNil) | 208 So(vals[1].Value, ShouldBeNil) |
| 215 So(vals[2].Value, ShouldResemble, []int6
4{1, 2, 3, 4}) | 209 So(vals[2].Value, ShouldResemble, []int6
4{1, 2, 3, 4}) |
| 216 So(vals[3].Value, ShouldResemble, dataSi
ngleRoot[3].Value) | 210 So(vals[3].Value, ShouldResemble, dataSi
ngleRoot[3].Value) |
| 217 | 211 |
| 218 // inner, failing, transaction | 212 // inner, failing, transaction |
| 219 » » » » » So(ds.RunInTransaction(func(c context.Co
ntext) error { | 213 » » » » » So(ds.RunInTransaction(c, func(c context
.Context) error { |
| 220 » » » » » » ds := datastore.Get(c) | 214 » » » » » » // we can see stuff written in t
he outer txn |
| 215 » » » » » » So(7, fooShouldHave(c)) |
| 216 » » » » » » So(3, fooShouldHave(c), 1, 2, 3,
4) |
| 221 | 217 |
| 222 » » » » » » // we can see stuff written in t
he outer txn | 218 » » » » » » So(3, fooSetTo(c), 10, 20, 30, 4
0) |
| 223 » » » » » » So(7, fooShouldHave(ds)) | |
| 224 » » » » » » So(3, fooShouldHave(ds), 1, 2, 3
, 4) | |
| 225 | |
| 226 » » » » » » So(3, fooSetTo(ds), 10, 20, 30,
40) | |
| 227 | 219 |
| 228 // disaster strikes! | 220 // disaster strikes! |
| 229 return errors.New("whaaaa") | 221 return errors.New("whaaaa") |
| 230 }, nil), ShouldErrLike, "whaaaa") | 222 }, nil), ShouldErrLike, "whaaaa") |
| 231 | 223 |
| 232 » » » » » So(3, fooShouldHave(ds), 1, 2, 3, 4) | 224 » » » » » So(3, fooShouldHave(c), 1, 2, 3, 4) |
| 233 | 225 |
| 234 // inner, successful, transaction | 226 // inner, successful, transaction |
| 235 » » » » » So(ds.RunInTransaction(func(c context.Co
ntext) error { | 227 » » » » » So(ds.RunInTransaction(c, func(c context
.Context) error { |
| 236 » » » » » » ds := datastore.Get(c) | 228 » » » » » » So(3, fooShouldHave(c), 1, 2, 3,
4) |
| 237 » » » » » » So(3, fooShouldHave(ds), 1, 2, 3
, 4) | 229 » » » » » » So(3, fooSetTo(c), 10, 20, 30, 4
0) |
| 238 » » » » » » So(3, fooSetTo(ds), 10, 20, 30,
40) | |
| 239 return nil | 230 return nil |
| 240 }, nil), ShouldBeNil) | 231 }, nil), ShouldBeNil) |
| 241 | 232 |
| 242 // now we see it | 233 // now we see it |
| 243 » » » » » So(3, fooShouldHave(ds), 10, 20, 30, 40) | 234 » » » » » So(3, fooShouldHave(c), 10, 20, 30, 40) |
| 244 return nil | 235 return nil |
| 245 » » » » }, &datastore.TransactionOptions{XG: true}), Sho
uldBeNil) | 236 » » » » }, &ds.TransactionOptions{XG: true}), ShouldBeNi
l) |
| 246 | 237 |
| 247 // 2 because we are simulating a transaction fai
lure | 238 // 2 because we are simulating a transaction fai
lure |
| 248 So(under.PutMulti.Total(), ShouldEqual, 2) | 239 So(under.PutMulti.Total(), ShouldEqual, 2) |
| 249 So(under.DeleteMulti.Total(), ShouldEqual, 2) | 240 So(under.DeleteMulti.Total(), ShouldEqual, 2) |
| 250 | 241 |
| 251 So(over.PutMulti.Total(), ShouldEqual, 8) | 242 So(over.PutMulti.Total(), ShouldEqual, 8) |
| 252 | 243 |
| 253 » » » » So(7, fooShouldHave(ds)) | 244 » » » » So(7, fooShouldHave(c)) |
| 254 » » » » So(3, fooShouldHave(ds), 10, 20, 30, 40) | 245 » » » » So(3, fooShouldHave(c), 10, 20, 30, 40) |
| 255 }) | 246 }) |
| 256 | 247 |
| 257 Convey("can allocate IDs from an inner transaction", fun
c() { | 248 Convey("can allocate IDs from an inner transaction", fun
c() { |
| 258 nums := []int64{4, 8, 15, 16, 23, 42} | 249 nums := []int64{4, 8, 15, 16, 23, 42} |
| 259 » » » » k := (*datastore.Key)(nil) | 250 » » » » k := (*ds.Key)(nil) |
| 260 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 251 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 261 » » » » » ds := datastore.Get(c) | 252 » » » » » So(ds.RunInTransaction(c, func(c context
.Context) error { |
| 262 | |
| 263 » » » » » So(ds.RunInTransaction(func(c context.Co
ntext) error { | |
| 264 » » » » » » ds := datastore.Get(c) | |
| 265 f := &Foo{Value: nums} | 253 f := &Foo{Value: nums} |
| 266 » » » » » » So(ds.Put(f), ShouldBeNil) | 254 » » » » » » So(ds.Put(c, f), ShouldBeNil) |
| 267 » » » » » » k = ds.KeyForObj(f) | 255 » » » » » » k = ds.KeyForObj(c, f) |
| 268 return nil | 256 return nil |
| 269 }, nil), ShouldBeNil) | 257 }, nil), ShouldBeNil) |
| 270 | 258 |
| 271 » » » » » So(k.IntID(), fooShouldHave(ds), nums) | 259 » » » » » So(k.IntID(), fooShouldHave(c), nums) |
| 272 | 260 |
| 273 return nil | 261 return nil |
| 274 }, nil), ShouldBeNil) | 262 }, nil), ShouldBeNil) |
| 275 | 263 |
| 276 » » » » So(k.IntID(), fooShouldHave(ds), nums) | 264 » » » » So(k.IntID(), fooShouldHave(c), nums) |
| 277 }) | 265 }) |
| 278 | 266 |
| 279 }) | 267 }) |
| 280 | 268 |
| 281 Convey("Bad", func() { | 269 Convey("Bad", func() { |
| 282 | 270 |
| 283 Convey("too many roots", func() { | 271 Convey("too many roots", func() { |
| 284 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 272 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 285 » » » » » ds := datastore.Get(c) | |
| 286 | |
| 287 f := &Foo{ID: 7} | 273 f := &Foo{ID: 7} |
| 288 » » » » » So(ds.Get(f), ShouldBeNil) | 274 » » » » » So(ds.Get(c, f), ShouldBeNil) |
| 289 So(f, ShouldResemble, dataMultiRoot[6]) | 275 So(f, ShouldResemble, dataMultiRoot[6]) |
| 290 | 276 |
| 291 » » » » » So(ds.RunInTransaction(func(c context.Co
ntext) error { | 277 » » » » » So(ds.RunInTransaction(c, func(c context
.Context) error { |
| 292 » » » » » » return datastore.Get(c).Get(&Foo
{ID: 6}) | 278 » » » » » » return ds.Get(c, &Foo{ID: 5}) |
| 293 }, nil), ShouldErrLike, "too many entity
groups") | 279 }, nil), ShouldErrLike, "too many entity
groups") |
| 294 | 280 |
| 295 f.Value = []int64{9} | 281 f.Value = []int64{9} |
| 296 » » » » » So(ds.Put(f), ShouldBeNil) | 282 » » » » » So(ds.Put(c, f), ShouldBeNil) |
| 297 | 283 |
| 298 return nil | 284 return nil |
| 299 }, nil), ShouldBeNil) | 285 }, nil), ShouldBeNil) |
| 300 | 286 |
| 301 f := &Foo{ID: 7} | 287 f := &Foo{ID: 7} |
| 302 » » » » So(ds.Get(f), ShouldBeNil) | 288 » » » » So(ds.Get(c, f), ShouldBeNil) |
| 303 So(f.Value, ShouldResemble, []int64{9}) | 289 So(f.Value, ShouldResemble, []int64{9}) |
| 304 }) | 290 }) |
| 305 | 291 |
| 306 Convey("buffered errors never reach the datastore", func
() { | 292 Convey("buffered errors never reach the datastore", func
() { |
| 307 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 293 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 308 » » » » » ds := datastore.Get(c) | 294 » » » » » So(ds.Put(c, &Foo{ID: 1, Value: []int64{
1, 2, 3, 4}}), ShouldBeNil) |
| 309 | |
| 310 » » » » » So(ds.Put(&Foo{ID: 1, Value: []int64{1,
2, 3, 4}}), ShouldBeNil) | |
| 311 return errors.New("boop") | 295 return errors.New("boop") |
| 312 }, nil), ShouldErrLike, "boop") | 296 }, nil), ShouldErrLike, "boop") |
| 313 So(under.PutMulti.Total(), ShouldEqual, 0) | 297 So(under.PutMulti.Total(), ShouldEqual, 0) |
| 314 So(over.PutMulti.Successes(), ShouldEqual, 1) | 298 So(over.PutMulti.Successes(), ShouldEqual, 1) |
| 315 }) | 299 }) |
| 316 | 300 |
| 317 }) | 301 }) |
| 318 | 302 |
| 319 }) | 303 }) |
| 320 } | 304 } |
| 321 | 305 |
| 322 func TestHuge(t *testing.T) { | 306 func TestHuge(t *testing.T) { |
| 323 t.Parallel() | 307 t.Parallel() |
| 324 | 308 |
| 325 Convey("testing datastore enforces thresholds", t, func() { | 309 Convey("testing datastore enforces thresholds", t, func() { |
| 326 » » _, _, ds := mkds(dataMultiRoot) | 310 » » _, _, c := mkds(dataMultiRoot) |
| 327 | 311 |
| 328 Convey("exceeding inner txn size threshold still allows outer",
func() { | 312 Convey("exceeding inner txn size threshold still allows outer",
func() { |
| 329 » » » So(ds.RunInTransaction(func(c context.Context) error { | 313 » » » So(ds.RunInTransaction(c, func(c context.Context) error
{ |
| 330 » » » » ds := datastore.Get(c) | 314 » » » » So(18, fooSetTo(c), hugeField) |
| 331 | 315 |
| 332 » » » » So(18, fooSetTo(ds), hugeField) | 316 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 333 | 317 » » » » » So(ds.Put(c, hugeData), ShouldBeNil) |
| 334 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | |
| 335 » » » » » ds := datastore.Get(c) | |
| 336 » » » » » So(ds.PutMulti(hugeData), ShouldBeNil) | |
| 337 return nil | 318 return nil |
| 338 }, nil), ShouldErrLike, ErrTransactionTooLarge) | 319 }, nil), ShouldErrLike, ErrTransactionTooLarge) |
| 339 | 320 |
| 340 return nil | 321 return nil |
| 341 » » » }, &datastore.TransactionOptions{XG: true}), ShouldBeNil
) | 322 » » » }, &ds.TransactionOptions{XG: true}), ShouldBeNil) |
| 342 | 323 |
| 343 » » » So(18, fooShouldHave(ds), hugeField) | 324 » » » So(18, fooShouldHave(c), hugeField) |
| 344 }) | 325 }) |
| 345 | 326 |
| 346 Convey("exceeding inner txn count threshold still allows outer",
func() { | 327 Convey("exceeding inner txn count threshold still allows outer",
func() { |
| 347 » » » So(ds.RunInTransaction(func(c context.Context) error { | 328 » » » So(ds.RunInTransaction(c, func(c context.Context) error
{ |
| 348 » » » » ds := datastore.Get(c) | 329 » » » » So(18, fooSetTo(c), hugeField) |
| 349 | 330 |
| 350 » » » » So(18, fooSetTo(ds), hugeField) | 331 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 351 | 332 » » » » » p := ds.MakeKey(c, "mom", 1) |
| 352 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | |
| 353 » » » » » ds := datastore.Get(c) | |
| 354 » » » » » p := ds.MakeKey("mom", 1) | |
| 355 | 333 |
| 356 // This will exceed the budget, since we
've already done one write in | 334 // This will exceed the budget, since we
've already done one write in |
| 357 // the parent. | 335 // the parent. |
| 358 for i := 1; i <= DefaultWriteCountBudget
; i++ { | 336 for i := 1; i <= DefaultWriteCountBudget
; i++ { |
| 359 » » » » » » So(ds.Put(&Foo{ID: int64(i), Par
ent: p}), ShouldBeNil) | 337 » » » » » » So(ds.Put(c, &Foo{ID: int64(i),
Parent: p}), ShouldBeNil) |
| 360 } | 338 } |
| 361 return nil | 339 return nil |
| 362 }, nil), ShouldErrLike, ErrTransactionTooLarge) | 340 }, nil), ShouldErrLike, ErrTransactionTooLarge) |
| 363 | 341 |
| 364 return nil | 342 return nil |
| 365 » » » }, &datastore.TransactionOptions{XG: true}), ShouldBeNil
) | 343 » » » }, &ds.TransactionOptions{XG: true}), ShouldBeNil) |
| 366 | 344 |
| 367 » » » So(18, fooShouldHave(ds), hugeField) | 345 » » » So(18, fooShouldHave(c), hugeField) |
| 368 }) | 346 }) |
| 369 | 347 |
| 370 Convey("exceeding threshold in the parent, then retreating in th
e child is okay", func() { | 348 Convey("exceeding threshold in the parent, then retreating in th
e child is okay", func() { |
| 371 » » » So(ds.RunInTransaction(func(c context.Context) error { | 349 » » » So(ds.RunInTransaction(c, func(c context.Context) error
{ |
| 372 » » » » ds := datastore.Get(c) | 350 » » » » So(ds.Put(c, hugeData), ShouldBeNil) |
| 373 | 351 » » » » So(18, fooSetTo(c), hugeField) |
| 374 » » » » So(ds.PutMulti(hugeData), ShouldBeNil) | |
| 375 » » » » So(18, fooSetTo(ds), hugeField) | |
| 376 | 352 |
| 377 // We're over threshold! But the child will dele
te most of this and | 353 // We're over threshold! But the child will dele
te most of this and |
| 378 // bring us back to normal. | 354 // bring us back to normal. |
| 379 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 355 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 380 » » » » » ds := datastore.Get(c) | 356 » » » » » keys := make([]*ds.Key, len(hugeData)) |
| 381 » » » » » keys := make([]*datastore.Key, len(hugeD
ata)) | |
| 382 for i, d := range hugeData { | 357 for i, d := range hugeData { |
| 383 » » » » » » keys[i] = ds.KeyForObj(d) | 358 » » » » » » keys[i] = ds.KeyForObj(c, d) |
| 384 } | 359 } |
| 385 » » » » » return ds.DeleteMulti(keys) | 360 » » » » » return ds.Delete(c, keys) |
| 386 }, nil), ShouldBeNil) | 361 }, nil), ShouldBeNil) |
| 387 | 362 |
| 388 return nil | 363 return nil |
| 389 » » » }, &datastore.TransactionOptions{XG: true}), ShouldBeNil
) | 364 » » » }, &ds.TransactionOptions{XG: true}), ShouldBeNil) |
| 390 | 365 |
| 391 » » » So(18, fooShouldHave(ds), hugeField) | 366 » » » So(18, fooShouldHave(c), hugeField) |
| 392 }) | 367 }) |
| 393 }) | 368 }) |
| 394 } | 369 } |
| 395 | 370 |
| 396 func TestQuerySupport(t *testing.T) { | 371 func TestQuerySupport(t *testing.T) { |
| 397 t.Parallel() | 372 t.Parallel() |
| 398 | 373 |
| 399 Convey("Queries", t, func() { | 374 Convey("Queries", t, func() { |
| 400 Convey("Good", func() { | 375 Convey("Good", func() { |
| 401 » » » q := datastore.NewQuery("Foo").Ancestor(root) | 376 » » » q := ds.NewQuery("Foo").Ancestor(root) |
| 402 | 377 |
| 403 Convey("normal", func() { | 378 Convey("normal", func() { |
| 404 » » » » _, _, ds := mkds(dataSingleRoot) | 379 » » » » _, _, c := mkds(dataSingleRoot) |
| 405 » » » » ds.Testable().AddIndexes(&datastore.IndexDefinit
ion{ | 380 » » » » ds.GetTestable(c).AddIndexes(&ds.IndexDefinition
{ |
| 406 Kind: "Foo", | 381 Kind: "Foo", |
| 407 Ancestor: true, | 382 Ancestor: true, |
| 408 » » » » » SortBy: []datastore.IndexColumn{ | 383 » » » » » SortBy: []ds.IndexColumn{ |
| 409 {Property: "Value"}, | 384 {Property: "Value"}, |
| 410 }, | 385 }, |
| 411 }) | 386 }) |
| 412 | 387 |
| 413 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 388 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 414 » » » » » ds := datastore.Get(c) | |
| 415 | |
| 416 q = q.Lt("Value", 400000000000000000) | 389 q = q.Lt("Value", 400000000000000000) |
| 417 | 390 |
| 418 vals := []*Foo{} | 391 vals := []*Foo{} |
| 419 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 392 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 420 So(len(vals), ShouldEqual, 8) | 393 So(len(vals), ShouldEqual, 8) |
| 421 | 394 |
| 422 » » » » » count, err := ds.Count(q) | 395 » » » » » count, err := ds.Count(c, q) |
| 423 So(err, ShouldBeNil) | 396 So(err, ShouldBeNil) |
| 424 So(count, ShouldEqual, 8) | 397 So(count, ShouldEqual, 8) |
| 425 | 398 |
| 426 f := &Foo{ID: 1, Parent: root} | 399 f := &Foo{ID: 1, Parent: root} |
| 427 » » » » » So(ds.Get(f), ShouldBeNil) | 400 » » » » » So(ds.Get(c, f), ShouldBeNil) |
| 428 f.Value = append(f.Value, 100) | 401 f.Value = append(f.Value, 100) |
| 429 » » » » » So(ds.Put(f), ShouldBeNil) | 402 » » » » » So(ds.Put(c, f), ShouldBeNil) |
| 430 | 403 |
| 431 // Wowee, zowee, merged queries! | 404 // Wowee, zowee, merged queries! |
| 432 vals2 := []*Foo{} | 405 vals2 := []*Foo{} |
| 433 » » » » » So(ds.GetAll(q, &vals2), ShouldBeNil) | 406 » » » » » So(ds.GetAll(c, q, &vals2), ShouldBeNil) |
| 434 So(len(vals2), ShouldEqual, 9) | 407 So(len(vals2), ShouldEqual, 9) |
| 435 So(vals2[0], ShouldResemble, f) | 408 So(vals2[0], ShouldResemble, f) |
| 436 | 409 |
| 437 vals2 = []*Foo{} | 410 vals2 = []*Foo{} |
| 438 » » » » » So(ds.GetAll(q.Limit(2).Offset(1), &vals
2), ShouldBeNil) | 411 » » » » » So(ds.GetAll(c, q.Limit(2).Offset(1), &v
als2), ShouldBeNil) |
| 439 So(len(vals2), ShouldEqual, 2) | 412 So(len(vals2), ShouldEqual, 2) |
| 440 So(vals2, ShouldResemble, vals[:2]) | 413 So(vals2, ShouldResemble, vals[:2]) |
| 441 | 414 |
| 442 return nil | 415 return nil |
| 443 }, nil), ShouldBeNil) | 416 }, nil), ShouldBeNil) |
| 444 }) | 417 }) |
| 445 | 418 |
| 446 Convey("keysOnly", func() { | 419 Convey("keysOnly", func() { |
| 447 » » » » _, _, ds := mkds([]*Foo{ | 420 » » » » _, _, c := mkds([]*Foo{ |
| 448 {ID: 2, Parent: root, Value: []int64{1,
2, 3, 4, 5, 6, 7}}, | 421 {ID: 2, Parent: root, Value: []int64{1,
2, 3, 4, 5, 6, 7}}, |
| 449 {ID: 3, Parent: root, Value: []int64{3,
4, 5, 6, 7, 8, 9}}, | 422 {ID: 3, Parent: root, Value: []int64{3,
4, 5, 6, 7, 8, 9}}, |
| 450 {ID: 4, Parent: root, Value: []int64{3,
5, 7, 9, 11, 100, 1}}, | 423 {ID: 4, Parent: root, Value: []int64{3,
5, 7, 9, 11, 100, 1}}, |
| 451 {ID: 5, Parent: root, Value: []int64{1,
70, 101}}, | 424 {ID: 5, Parent: root, Value: []int64{1,
70, 101}}, |
| 452 }) | 425 }) |
| 453 | 426 |
| 454 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 427 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 455 » » » » » ds := datastore.Get(c) | |
| 456 | |
| 457 q = q.Eq("Value", 1).KeysOnly(true) | 428 q = q.Eq("Value", 1).KeysOnly(true) |
| 458 » » » » » vals := []*datastore.Key{} | 429 » » » » » vals := []*ds.Key{} |
| 459 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 430 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 460 So(len(vals), ShouldEqual, 3) | 431 So(len(vals), ShouldEqual, 3) |
| 461 » » » » » So(vals[2], ShouldResemble, ds.MakeKey("
Parent", 1, "Foo", 5)) | 432 » » » » » So(vals[2], ShouldResemble, ds.MakeKey(c
, "Parent", 1, "Foo", 5)) |
| 462 | 433 |
| 463 // can remove keys | 434 // can remove keys |
| 464 » » » » » So(ds.Delete(ds.MakeKey("Parent", 1, "Fo
o", 2)), ShouldBeNil) | 435 » » » » » So(ds.Delete(c, ds.MakeKey(c, "Parent",
1, "Foo", 2)), ShouldBeNil) |
| 465 » » » » » vals = []*datastore.Key{} | 436 » » » » » vals = []*ds.Key{} |
| 466 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 437 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 467 So(len(vals), ShouldEqual, 2) | 438 So(len(vals), ShouldEqual, 2) |
| 468 | 439 |
| 469 // and add new ones | 440 // and add new ones |
| 470 » » » » » So(ds.Put(&Foo{ID: 1, Parent: root, Valu
e: []int64{1, 7, 100}}), ShouldBeNil) | 441 » » » » » So(ds.Put(c, &Foo{ID: 1, Parent: root, V
alue: []int64{1, 7, 100}}), ShouldBeNil) |
| 471 » » » » » So(ds.Put(&Foo{ID: 7, Parent: root, Valu
e: []int64{20, 1}}), ShouldBeNil) | 442 » » » » » So(ds.Put(c, &Foo{ID: 7, Parent: root, V
alue: []int64{20, 1}}), ShouldBeNil) |
| 472 » » » » » vals = []*datastore.Key{} | 443 » » » » » vals = []*ds.Key{} |
| 473 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 444 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 474 So(len(vals), ShouldEqual, 4) | 445 So(len(vals), ShouldEqual, 4) |
| 475 | 446 |
| 476 So(vals[0].IntID(), ShouldEqual, 1) | 447 So(vals[0].IntID(), ShouldEqual, 1) |
| 477 So(vals[1].IntID(), ShouldEqual, 4) | 448 So(vals[1].IntID(), ShouldEqual, 4) |
| 478 So(vals[2].IntID(), ShouldEqual, 5) | 449 So(vals[2].IntID(), ShouldEqual, 5) |
| 479 So(vals[3].IntID(), ShouldEqual, 7) | 450 So(vals[3].IntID(), ShouldEqual, 7) |
| 480 | 451 |
| 481 return nil | 452 return nil |
| 482 }, nil), ShouldBeNil) | 453 }, nil), ShouldBeNil) |
| 483 }) | 454 }) |
| 484 | 455 |
| 485 Convey("project", func() { | 456 Convey("project", func() { |
| 486 » » » » _, _, ds := mkds([]*Foo{ | 457 » » » » _, _, c := mkds([]*Foo{ |
| 487 {ID: 2, Parent: root, Value: []int64{1,
2, 3, 4, 5, 6, 7}}, | 458 {ID: 2, Parent: root, Value: []int64{1,
2, 3, 4, 5, 6, 7}}, |
| 488 {ID: 3, Parent: root, Value: []int64{3,
4, 5, 6, 7, 8, 9}}, | 459 {ID: 3, Parent: root, Value: []int64{3,
4, 5, 6, 7, 8, 9}}, |
| 489 {ID: 4, Parent: root, Value: []int64{3,
5, 7, 9, 11, 100, 1}}, | 460 {ID: 4, Parent: root, Value: []int64{3,
5, 7, 9, 11, 100, 1}}, |
| 490 {ID: 5, Parent: root, Value: []int64{1,
70, 101}}, | 461 {ID: 5, Parent: root, Value: []int64{1,
70, 101}}, |
| 491 }) | 462 }) |
| 492 | 463 |
| 493 » » » » ds.Testable().AddIndexes(&datastore.IndexDefinit
ion{ | 464 » » » » ds.GetTestable(c).AddIndexes(&ds.IndexDefinition
{ |
| 494 Kind: "Foo", | 465 Kind: "Foo", |
| 495 Ancestor: true, | 466 Ancestor: true, |
| 496 » » » » » SortBy: []datastore.IndexColumn{ | 467 » » » » » SortBy: []ds.IndexColumn{ |
| 497 {Property: "Value"}, | 468 {Property: "Value"}, |
| 498 }, | 469 }, |
| 499 }) | 470 }) |
| 500 | 471 |
| 501 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 472 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 502 » » » » » ds := datastore.Get(c) | 473 » » » » » count, err := ds.Count(c, q.Project("Val
ue")) |
| 503 | |
| 504 » » » » » count, err := ds.Count(q.Project("Value"
)) | |
| 505 So(err, ShouldBeNil) | 474 So(err, ShouldBeNil) |
| 506 So(count, ShouldEqual, 24) | 475 So(count, ShouldEqual, 24) |
| 507 | 476 |
| 508 q = q.Project("Value").Offset(4).Limit(1
0) | 477 q = q.Project("Value").Offset(4).Limit(1
0) |
| 509 | 478 |
| 510 » » » » » vals := []datastore.PropertyMap{} | 479 » » » » » vals := []ds.PropertyMap{} |
| 511 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 480 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 512 So(len(vals), ShouldEqual, 10) | 481 So(len(vals), ShouldEqual, 10) |
| 513 | 482 |
| 514 expect := []struct { | 483 expect := []struct { |
| 515 id int64 | 484 id int64 |
| 516 val int64 | 485 val int64 |
| 517 }{ | 486 }{ |
| 518 {2, 3}, | 487 {2, 3}, |
| 519 {3, 3}, | 488 {3, 3}, |
| 520 {4, 3}, | 489 {4, 3}, |
| 521 {2, 4}, | 490 {2, 4}, |
| 522 {3, 4}, | 491 {3, 4}, |
| 523 {2, 5}, | 492 {2, 5}, |
| 524 {3, 5}, | 493 {3, 5}, |
| 525 {4, 5}, | 494 {4, 5}, |
| 526 {2, 6}, | 495 {2, 6}, |
| 527 {3, 6}, | 496 {3, 6}, |
| 528 } | 497 } |
| 529 | 498 |
| 530 for i, pm := range vals { | 499 for i, pm := range vals { |
| 531 » » » » » » So(datastore.GetMetaDefault(pm,
"key", nil), ShouldResemble, | 500 » » » » » » So(ds.GetMetaDefault(pm, "key",
nil), ShouldResemble, |
| 532 » » » » » » » ds.MakeKey("Parent", 1,
"Foo", expect[i].id)) | 501 » » » » » » » ds.MakeKey(c, "Parent",
1, "Foo", expect[i].id)) |
| 533 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) | 502 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) |
| 534 } | 503 } |
| 535 | 504 |
| 536 // should remove 4 entries, but there ar
e plenty more to fill | 505 // should remove 4 entries, but there ar
e plenty more to fill |
| 537 » » » » » So(ds.Delete(ds.MakeKey("Parent", 1, "Fo
o", 2)), ShouldBeNil) | 506 » » » » » So(ds.Delete(c, ds.MakeKey(c, "Parent",
1, "Foo", 2)), ShouldBeNil) |
| 538 | 507 |
| 539 » » » » » vals = []datastore.PropertyMap{} | 508 » » » » » vals = []ds.PropertyMap{} |
| 540 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 509 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 541 So(len(vals), ShouldEqual, 10) | 510 So(len(vals), ShouldEqual, 10) |
| 542 | 511 |
| 543 expect = []struct { | 512 expect = []struct { |
| 544 id int64 | 513 id int64 |
| 545 val int64 | 514 val int64 |
| 546 }{ | 515 }{ |
| 547 // note (3, 3) and (4, 3) are co
rrectly missing because deleting | 516 // note (3, 3) and (4, 3) are co
rrectly missing because deleting |
| 548 // 2 removed two entries which a
re hidden by the Offset(4). | 517 // 2 removed two entries which a
re hidden by the Offset(4). |
| 549 {3, 4}, | 518 {3, 4}, |
| 550 {3, 5}, | 519 {3, 5}, |
| 551 {4, 5}, | 520 {4, 5}, |
| 552 {3, 6}, | 521 {3, 6}, |
| 553 {3, 7}, | 522 {3, 7}, |
| 554 {4, 7}, | 523 {4, 7}, |
| 555 {3, 8}, | 524 {3, 8}, |
| 556 {3, 9}, | 525 {3, 9}, |
| 557 {4, 9}, | 526 {4, 9}, |
| 558 {4, 11}, | 527 {4, 11}, |
| 559 } | 528 } |
| 560 | 529 |
| 561 for i, pm := range vals { | 530 for i, pm := range vals { |
| 562 » » » » » » So(datastore.GetMetaDefault(pm,
"key", nil), ShouldResemble, | 531 » » » » » » So(ds.GetMetaDefault(pm, "key",
nil), ShouldResemble, |
| 563 » » » » » » » ds.MakeKey("Parent", 1,
"Foo", expect[i].id)) | 532 » » » » » » » ds.MakeKey(c, "Parent",
1, "Foo", expect[i].id)) |
| 564 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) | 533 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) |
| 565 } | 534 } |
| 566 | 535 |
| 567 » » » » » So(ds.Put(&Foo{ID: 1, Parent: root, Valu
e: []int64{3, 9}}), ShouldBeNil) | 536 » » » » » So(ds.Put(c, &Foo{ID: 1, Parent: root, V
alue: []int64{3, 9}}), ShouldBeNil) |
| 568 | 537 |
| 569 » » » » » vals = []datastore.PropertyMap{} | 538 » » » » » vals = []ds.PropertyMap{} |
| 570 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 539 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 571 So(len(vals), ShouldEqual, 10) | 540 So(len(vals), ShouldEqual, 10) |
| 572 | 541 |
| 573 expect = []struct { | 542 expect = []struct { |
| 574 id int64 | 543 id int64 |
| 575 val int64 | 544 val int64 |
| 576 }{ | 545 }{ |
| 577 // 'invisible' {1, 3} entry bump
s the {4, 3} into view. | 546 // 'invisible' {1, 3} entry bump
s the {4, 3} into view. |
| 578 {4, 3}, | 547 {4, 3}, |
| 579 {3, 4}, | 548 {3, 4}, |
| 580 {3, 5}, | 549 {3, 5}, |
| 581 {4, 5}, | 550 {4, 5}, |
| 582 {3, 6}, | 551 {3, 6}, |
| 583 {3, 7}, | 552 {3, 7}, |
| 584 {4, 7}, | 553 {4, 7}, |
| 585 {3, 8}, | 554 {3, 8}, |
| 586 {1, 9}, | 555 {1, 9}, |
| 587 {3, 9}, | 556 {3, 9}, |
| 588 {4, 9}, | 557 {4, 9}, |
| 589 } | 558 } |
| 590 | 559 |
| 591 for i, pm := range vals { | 560 for i, pm := range vals { |
| 592 » » » » » » So(datastore.GetMetaDefault(pm,
"key", nil), ShouldResemble, | 561 » » » » » » So(ds.GetMetaDefault(pm, "key",
nil), ShouldResemble, |
| 593 » » » » » » » ds.MakeKey("Parent", 1,
"Foo", expect[i].id)) | 562 » » » » » » » ds.MakeKey(c, "Parent",
1, "Foo", expect[i].id)) |
| 594 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) | 563 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) |
| 595 } | 564 } |
| 596 | 565 |
| 597 return nil | 566 return nil |
| 598 }, nil), ShouldBeNil) | 567 }, nil), ShouldBeNil) |
| 599 | 568 |
| 600 }) | 569 }) |
| 601 | 570 |
| 602 Convey("project+distinct", func() { | 571 Convey("project+distinct", func() { |
| 603 » » » » _, _, ds := mkds([]*Foo{ | 572 » » » » _, _, c := mkds([]*Foo{ |
| 604 {ID: 2, Parent: root, Value: []int64{1,
2, 3, 4, 5, 6, 7}}, | 573 {ID: 2, Parent: root, Value: []int64{1,
2, 3, 4, 5, 6, 7}}, |
| 605 {ID: 3, Parent: root, Value: []int64{3,
4, 5, 6, 7, 8, 9}}, | 574 {ID: 3, Parent: root, Value: []int64{3,
4, 5, 6, 7, 8, 9}}, |
| 606 {ID: 4, Parent: root, Value: []int64{3,
5, 7, 9, 11, 100, 1}}, | 575 {ID: 4, Parent: root, Value: []int64{3,
5, 7, 9, 11, 100, 1}}, |
| 607 {ID: 5, Parent: root, Value: []int64{1,
70, 101}}, | 576 {ID: 5, Parent: root, Value: []int64{1,
70, 101}}, |
| 608 }) | 577 }) |
| 609 | 578 |
| 610 » » » » ds.Testable().AddIndexes(&datastore.IndexDefinit
ion{ | 579 » » » » ds.GetTestable(c).AddIndexes(&ds.IndexDefinition
{ |
| 611 Kind: "Foo", | 580 Kind: "Foo", |
| 612 Ancestor: true, | 581 Ancestor: true, |
| 613 » » » » » SortBy: []datastore.IndexColumn{ | 582 » » » » » SortBy: []ds.IndexColumn{ |
| 614 {Property: "Value"}, | 583 {Property: "Value"}, |
| 615 }, | 584 }, |
| 616 }) | 585 }) |
| 617 | 586 |
| 618 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 587 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 619 » » » » » ds := datastore.Get(c) | |
| 620 | |
| 621 q = q.Project("Value").Distinct(true) | 588 q = q.Project("Value").Distinct(true) |
| 622 | 589 |
| 623 » » » » » vals := []datastore.PropertyMap{} | 590 » » » » » vals := []ds.PropertyMap{} |
| 624 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 591 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 625 So(len(vals), ShouldEqual, 13) | 592 So(len(vals), ShouldEqual, 13) |
| 626 | 593 |
| 627 expect := []struct { | 594 expect := []struct { |
| 628 id int64 | 595 id int64 |
| 629 val int64 | 596 val int64 |
| 630 }{ | 597 }{ |
| 631 {2, 1}, | 598 {2, 1}, |
| 632 {2, 2}, | 599 {2, 2}, |
| 633 {2, 3}, | 600 {2, 3}, |
| 634 {2, 4}, | 601 {2, 4}, |
| 635 {2, 5}, | 602 {2, 5}, |
| 636 {2, 6}, | 603 {2, 6}, |
| 637 {2, 7}, | 604 {2, 7}, |
| 638 {3, 8}, | 605 {3, 8}, |
| 639 {3, 9}, | 606 {3, 9}, |
| 640 {4, 11}, | 607 {4, 11}, |
| 641 {5, 70}, | 608 {5, 70}, |
| 642 {4, 100}, | 609 {4, 100}, |
| 643 {5, 101}, | 610 {5, 101}, |
| 644 } | 611 } |
| 645 | 612 |
| 646 for i, pm := range vals { | 613 for i, pm := range vals { |
| 647 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) | 614 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) |
| 648 » » » » » » So(datastore.GetMetaDefault(pm,
"key", nil), ShouldResemble, | 615 » » » » » » So(ds.GetMetaDefault(pm, "key",
nil), ShouldResemble, |
| 649 » » » » » » » ds.MakeKey("Parent", 1,
"Foo", expect[i].id)) | 616 » » » » » » » ds.MakeKey(c, "Parent",
1, "Foo", expect[i].id)) |
| 650 } | 617 } |
| 651 | 618 |
| 652 return nil | 619 return nil |
| 653 }, nil), ShouldBeNil) | 620 }, nil), ShouldBeNil) |
| 654 }) | 621 }) |
| 655 | 622 |
| 656 Convey("overwrite", func() { | 623 Convey("overwrite", func() { |
| 657 data := []*Foo{ | 624 data := []*Foo{ |
| 658 {ID: 2, Parent: root, Value: []int64{1,
2, 3, 4, 5, 6, 7}}, | 625 {ID: 2, Parent: root, Value: []int64{1,
2, 3, 4, 5, 6, 7}}, |
| 659 {ID: 3, Parent: root, Value: []int64{3,
4, 5, 6, 7, 8, 9}}, | 626 {ID: 3, Parent: root, Value: []int64{3,
4, 5, 6, 7, 8, 9}}, |
| 660 {ID: 4, Parent: root, Value: []int64{3,
5, 7, 9, 11, 100, 1, 2}}, | 627 {ID: 4, Parent: root, Value: []int64{3,
5, 7, 9, 11, 100, 1, 2}}, |
| 661 {ID: 5, Parent: root, Value: []int64{1,
70, 101}}, | 628 {ID: 5, Parent: root, Value: []int64{1,
70, 101}}, |
| 662 } | 629 } |
| 663 | 630 |
| 664 » » » » _, _, ds := mkds(data) | 631 » » » » _, _, c := mkds(data) |
| 665 | 632 |
| 666 q = q.Eq("Value", 2, 3) | 633 q = q.Eq("Value", 2, 3) |
| 667 | 634 |
| 668 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 635 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 669 » » » » » ds := datastore.Get(c) | |
| 670 | |
| 671 vals := []*Foo{} | 636 vals := []*Foo{} |
| 672 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 637 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 673 So(len(vals), ShouldEqual, 2) | 638 So(len(vals), ShouldEqual, 2) |
| 674 | 639 |
| 675 So(vals[0], ShouldResemble, data[0]) | 640 So(vals[0], ShouldResemble, data[0]) |
| 676 So(vals[1], ShouldResemble, data[2]) | 641 So(vals[1], ShouldResemble, data[2]) |
| 677 | 642 |
| 678 foo2 := &Foo{ID: 2, Parent: root, Value:
[]int64{2, 3}} | 643 foo2 := &Foo{ID: 2, Parent: root, Value:
[]int64{2, 3}} |
| 679 » » » » » So(ds.Put(foo2), ShouldBeNil) | 644 » » » » » So(ds.Put(c, foo2), ShouldBeNil) |
| 680 | 645 |
| 681 vals = []*Foo{} | 646 vals = []*Foo{} |
| 682 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 647 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 683 So(len(vals), ShouldEqual, 2) | 648 So(len(vals), ShouldEqual, 2) |
| 684 | 649 |
| 685 So(vals[0], ShouldResemble, foo2) | 650 So(vals[0], ShouldResemble, foo2) |
| 686 So(vals[1], ShouldResemble, data[2]) | 651 So(vals[1], ShouldResemble, data[2]) |
| 687 | 652 |
| 688 foo1 := &Foo{ID: 1, Parent: root, Value:
[]int64{2, 3}} | 653 foo1 := &Foo{ID: 1, Parent: root, Value:
[]int64{2, 3}} |
| 689 » » » » » So(ds.Put(foo1), ShouldBeNil) | 654 » » » » » So(ds.Put(c, foo1), ShouldBeNil) |
| 690 | 655 |
| 691 vals = []*Foo{} | 656 vals = []*Foo{} |
| 692 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 657 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 693 So(len(vals), ShouldEqual, 3) | 658 So(len(vals), ShouldEqual, 3) |
| 694 | 659 |
| 695 So(vals[0], ShouldResemble, foo1) | 660 So(vals[0], ShouldResemble, foo1) |
| 696 So(vals[1], ShouldResemble, foo2) | 661 So(vals[1], ShouldResemble, foo2) |
| 697 So(vals[2], ShouldResemble, data[2]) | 662 So(vals[2], ShouldResemble, data[2]) |
| 698 | 663 |
| 699 return nil | 664 return nil |
| 700 }, nil), ShouldBeNil) | 665 }, nil), ShouldBeNil) |
| 701 }) | 666 }) |
| 702 | 667 |
| 703 projectData := []*Foo{ | 668 projectData := []*Foo{ |
| 704 {ID: 2, Parent: root, Value: []int64{1, 2, 3, 4,
5, 6, 7}, Sort: []string{"x", "z"}}, | 669 {ID: 2, Parent: root, Value: []int64{1, 2, 3, 4,
5, 6, 7}, Sort: []string{"x", "z"}}, |
| 705 {ID: 3, Parent: root, Value: []int64{3, 4, 5, 6,
7, 8, 9}, Sort: []string{"b"}}, | 670 {ID: 3, Parent: root, Value: []int64{3, 4, 5, 6,
7, 8, 9}, Sort: []string{"b"}}, |
| 706 {ID: 4, Parent: root, Value: []int64{3, 5, 7, 9,
11, 100, 1, 2}, Sort: []string{"aa", "a"}}, | 671 {ID: 4, Parent: root, Value: []int64{3, 5, 7, 9,
11, 100, 1, 2}, Sort: []string{"aa", "a"}}, |
| 707 {ID: 5, Parent: root, Value: []int64{1, 70, 101}
, Sort: []string{"c"}}, | 672 {ID: 5, Parent: root, Value: []int64{1, 70, 101}
, Sort: []string{"c"}}, |
| 708 } | 673 } |
| 709 | 674 |
| 710 Convey("project+extra orders", func() { | 675 Convey("project+extra orders", func() { |
| 711 | 676 |
| 712 » » » » _, _, ds := mkds(projectData) | 677 » » » » _, _, c := mkds(projectData) |
| 713 » » » » ds.Testable().AddIndexes(&datastore.IndexDefinit
ion{ | 678 » » » » ds.GetTestable(c).AddIndexes(&ds.IndexDefinition
{ |
| 714 Kind: "Foo", | 679 Kind: "Foo", |
| 715 Ancestor: true, | 680 Ancestor: true, |
| 716 » » » » » SortBy: []datastore.IndexColumn{ | 681 » » » » » SortBy: []ds.IndexColumn{ |
| 717 {Property: "Sort", Descending: t
rue}, | 682 {Property: "Sort", Descending: t
rue}, |
| 718 {Property: "Value", Descending:
true}, | 683 {Property: "Value", Descending:
true}, |
| 719 }, | 684 }, |
| 720 }) | 685 }) |
| 721 | 686 |
| 722 q = q.Project("Value").Order("-Sort", "-Value").
Distinct(true) | 687 q = q.Project("Value").Order("-Sort", "-Value").
Distinct(true) |
| 723 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 688 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 724 » » » » » ds = datastore.Get(c) | 689 » » » » » So(ds.Put(c, &Foo{ |
| 725 | |
| 726 » » » » » So(ds.Put(&Foo{ | |
| 727 ID: 1, Parent: root, Value: []in
t64{0, 1, 1000}, | 690 ID: 1, Parent: root, Value: []in
t64{0, 1, 1000}, |
| 728 Sort: []string{"zz"}}), ShouldBe
Nil) | 691 Sort: []string{"zz"}}), ShouldBe
Nil) |
| 729 | 692 |
| 730 » » » » » vals := []datastore.PropertyMap{} | 693 » » » » » vals := []ds.PropertyMap{} |
| 731 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 694 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 732 | 695 |
| 733 expect := []struct { | 696 expect := []struct { |
| 734 id int64 | 697 id int64 |
| 735 val int64 | 698 val int64 |
| 736 }{ | 699 }{ |
| 737 {1, 1000}, | 700 {1, 1000}, |
| 738 {1, 1}, | 701 {1, 1}, |
| 739 {1, 0}, | 702 {1, 0}, |
| 740 {2, 7}, | 703 {2, 7}, |
| 741 {2, 6}, | 704 {2, 6}, |
| 742 {2, 5}, | 705 {2, 5}, |
| 743 {2, 4}, | 706 {2, 4}, |
| 744 {2, 3}, | 707 {2, 3}, |
| 745 {2, 2}, | 708 {2, 2}, |
| 746 {5, 101}, | 709 {5, 101}, |
| 747 {5, 70}, | 710 {5, 70}, |
| 748 {3, 9}, | 711 {3, 9}, |
| 749 {3, 8}, | 712 {3, 8}, |
| 750 {4, 100}, | 713 {4, 100}, |
| 751 {4, 11}, | 714 {4, 11}, |
| 752 } | 715 } |
| 753 | 716 |
| 754 for i, pm := range vals { | 717 for i, pm := range vals { |
| 755 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) | 718 So(pm.Slice("Value")[0].Value(),
ShouldEqual, expect[i].val) |
| 756 » » » » » » So(datastore.GetMetaDefault(pm,
"key", nil), ShouldResemble, | 719 » » » » » » So(ds.GetMetaDefault(pm, "key",
nil), ShouldResemble, |
| 757 » » » » » » » ds.MakeKey("Parent", 1,
"Foo", expect[i].id)) | 720 » » » » » » » ds.MakeKey(c, "Parent",
1, "Foo", expect[i].id)) |
| 758 } | 721 } |
| 759 | 722 |
| 760 return nil | 723 return nil |
| 761 }, nil), ShouldBeNil) | 724 }, nil), ShouldBeNil) |
| 762 }) | 725 }) |
| 763 | 726 |
| 764 Convey("buffered entity sorts before ineq, but after fir
st parent entity", func() { | 727 Convey("buffered entity sorts before ineq, but after fir
st parent entity", func() { |
| 765 // If we got this wrong, we'd see Foo,3 come bef
ore Foo,2. This might | 728 // If we got this wrong, we'd see Foo,3 come bef
ore Foo,2. This might |
| 766 // happen because we calculate the comparison st
ring for each entity | 729 // happen because we calculate the comparison st
ring for each entity |
| 767 // based on the whole entity, but we forgot to l
imit the comparison | 730 // based on the whole entity, but we forgot to l
imit the comparison |
| 768 // string generation by the inequality criteria. | 731 // string generation by the inequality criteria. |
| 769 data := []*Foo{ | 732 data := []*Foo{ |
| 770 {ID: 2, Parent: root, Value: []int64{2,
3, 5, 6}, Sort: []string{"z"}}, | 733 {ID: 2, Parent: root, Value: []int64{2,
3, 5, 6}, Sort: []string{"z"}}, |
| 771 } | 734 } |
| 772 | 735 |
| 773 » » » » _, _, ds := mkds(data) | 736 » » » » _, _, c := mkds(data) |
| 774 » » » » ds.Testable().AddIndexes(&datastore.IndexDefinit
ion{ | 737 » » » » ds.GetTestable(c).AddIndexes(&ds.IndexDefinition
{ |
| 775 Kind: "Foo", | 738 Kind: "Foo", |
| 776 Ancestor: true, | 739 Ancestor: true, |
| 777 » » » » » SortBy: []datastore.IndexColumn{ | 740 » » » » » SortBy: []ds.IndexColumn{ |
| 778 {Property: "Value"}, | 741 {Property: "Value"}, |
| 779 }, | 742 }, |
| 780 }) | 743 }) |
| 781 | 744 |
| 782 q = q.Gt("Value", 2).Limit(2) | 745 q = q.Gt("Value", 2).Limit(2) |
| 783 | 746 |
| 784 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 747 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 785 » » » » » ds = datastore.Get(c) | |
| 786 | |
| 787 foo1 := &Foo{ID: 3, Parent: root, Value:
[]int64{0, 2, 3, 4}} | 748 foo1 := &Foo{ID: 3, Parent: root, Value:
[]int64{0, 2, 3, 4}} |
| 788 » » » » » So(ds.Put(foo1), ShouldBeNil) | 749 » » » » » So(ds.Put(c, foo1), ShouldBeNil) |
| 789 | 750 |
| 790 vals := []*Foo{} | 751 vals := []*Foo{} |
| 791 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 752 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 792 So(len(vals), ShouldEqual, 2) | 753 So(len(vals), ShouldEqual, 2) |
| 793 | 754 |
| 794 So(vals[0], ShouldResemble, data[0]) | 755 So(vals[0], ShouldResemble, data[0]) |
| 795 So(vals[1], ShouldResemble, foo1) | 756 So(vals[1], ShouldResemble, foo1) |
| 796 | 757 |
| 797 return nil | 758 return nil |
| 798 }, nil), ShouldBeNil) | 759 }, nil), ShouldBeNil) |
| 799 }) | 760 }) |
| 800 | 761 |
| 801 Convey("keysOnly+extra orders", func() { | 762 Convey("keysOnly+extra orders", func() { |
| 802 » » » » _, _, ds := mkds(projectData) | 763 » » » » _, _, c := mkds(projectData) |
| 803 » » » » ds.Testable().AddIndexes(&datastore.IndexDefinit
ion{ | 764 » » » » ds.GetTestable(c).AddIndexes(&ds.IndexDefinition
{ |
| 804 Kind: "Foo", | 765 Kind: "Foo", |
| 805 Ancestor: true, | 766 Ancestor: true, |
| 806 » » » » » SortBy: []datastore.IndexColumn{ | 767 » » » » » SortBy: []ds.IndexColumn{ |
| 807 {Property: "Sort"}, | 768 {Property: "Sort"}, |
| 808 }, | 769 }, |
| 809 }) | 770 }) |
| 810 | 771 |
| 811 q = q.Order("Sort").KeysOnly(true) | 772 q = q.Order("Sort").KeysOnly(true) |
| 812 | 773 |
| 813 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 774 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 814 » » » » » ds = datastore.Get(c) | 775 » » » » » So(ds.Put(c, &Foo{ |
| 815 | |
| 816 » » » » » So(ds.Put(&Foo{ | |
| 817 ID: 1, Parent: root, Value: []in
t64{0, 1, 1000}, | 776 ID: 1, Parent: root, Value: []in
t64{0, 1, 1000}, |
| 818 Sort: []string{"x", "zz"}}), Sho
uldBeNil) | 777 Sort: []string{"x", "zz"}}), Sho
uldBeNil) |
| 819 | 778 |
| 820 » » » » » So(ds.Put(&Foo{ | 779 » » » » » So(ds.Put(c, &Foo{ |
| 821 ID: 2, Parent: root, Value: []in
t64{0, 1, 1000}, | 780 ID: 2, Parent: root, Value: []in
t64{0, 1, 1000}, |
| 822 Sort: []string{"zz", "zzz", "zzz
z"}}), ShouldBeNil) | 781 Sort: []string{"zz", "zzz", "zzz
z"}}), ShouldBeNil) |
| 823 | 782 |
| 824 » » » » » vals := []*datastore.Key{} | 783 » » » » » vals := []*ds.Key{} |
| 825 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 784 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 826 So(len(vals), ShouldEqual, 5) | 785 So(len(vals), ShouldEqual, 5) |
| 827 | 786 |
| 828 » » » » » So(vals, ShouldResemble, []*datastore.Ke
y{ | 787 » » » » » kc := ds.GetKeyContext(c) |
| 829 » » » » » » ds.MakeKey("Parent", 1, "Foo", 4
), | 788 » » » » » So(vals, ShouldResemble, []*ds.Key{ |
| 830 » » » » » » ds.MakeKey("Parent", 1, "Foo", 3
), | 789 » » » » » » kc.MakeKey("Parent", 1, "Foo", 4
), |
| 831 » » » » » » ds.MakeKey("Parent", 1, "Foo", 5
), | 790 » » » » » » kc.MakeKey("Parent", 1, "Foo", 3
), |
| 832 » » » » » » ds.MakeKey("Parent", 1, "Foo", 1
), | 791 » » » » » » kc.MakeKey("Parent", 1, "Foo", 5
), |
| 833 » » » » » » ds.MakeKey("Parent", 1, "Foo", 2
), | 792 » » » » » » kc.MakeKey("Parent", 1, "Foo", 1
), |
| 793 » » » » » » kc.MakeKey("Parent", 1, "Foo", 2
), |
| 834 }) | 794 }) |
| 835 | 795 |
| 836 return nil | 796 return nil |
| 837 }, nil), ShouldBeNil) | 797 }, nil), ShouldBeNil) |
| 838 }) | 798 }) |
| 839 | 799 |
| 840 Convey("query accross nested transactions", func() { | 800 Convey("query accross nested transactions", func() { |
| 841 » » » » _, _, ds := mkds(projectData) | 801 » » » » _, _, c := mkds(projectData) |
| 842 q = q.Eq("Value", 2, 3) | 802 q = q.Eq("Value", 2, 3) |
| 843 | 803 |
| 844 foo1 := &Foo{ID: 1, Parent: root, Value: []int64
{2, 3}} | 804 foo1 := &Foo{ID: 1, Parent: root, Value: []int64
{2, 3}} |
| 845 foo7 := &Foo{ID: 7, Parent: root, Value: []int64
{2, 3}} | 805 foo7 := &Foo{ID: 7, Parent: root, Value: []int64
{2, 3}} |
| 846 | 806 |
| 847 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 807 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 848 » » » » » ds := datastore.Get(c) | 808 » » » » » So(ds.Put(c, foo1), ShouldBeNil) |
| 849 | |
| 850 » » » » » So(ds.Put(foo1), ShouldBeNil) | |
| 851 | 809 |
| 852 vals := []*Foo{} | 810 vals := []*Foo{} |
| 853 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 811 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 854 So(vals, ShouldResemble, []*Foo{foo1, pr
ojectData[0], projectData[2]}) | 812 So(vals, ShouldResemble, []*Foo{foo1, pr
ojectData[0], projectData[2]}) |
| 855 | 813 |
| 856 » » » » » So(ds.RunInTransaction(func(c context.Co
ntext) error { | 814 » » » » » So(ds.RunInTransaction(c, func(c context
.Context) error { |
| 857 » » » » » » ds := datastore.Get(c) | |
| 858 | |
| 859 vals := []*Foo{} | 815 vals := []*Foo{} |
| 860 » » » » » » So(ds.GetAll(q, &vals), ShouldBe
Nil) | 816 » » » » » » So(ds.GetAll(c, q, &vals), Shoul
dBeNil) |
| 861 So(vals, ShouldResemble, []*Foo{
foo1, projectData[0], projectData[2]}) | 817 So(vals, ShouldResemble, []*Foo{
foo1, projectData[0], projectData[2]}) |
| 862 | 818 |
| 863 » » » » » » So(ds.Delete(ds.MakeKey("Parent"
, 1, "Foo", 4)), ShouldBeNil) | 819 » » » » » » So(ds.Delete(c, ds.MakeKey(c, "P
arent", 1, "Foo", 4)), ShouldBeNil) |
| 864 » » » » » » So(ds.Put(foo7), ShouldBeNil) | 820 » » » » » » So(ds.Put(c, foo7), ShouldBeNil) |
| 865 | 821 |
| 866 vals = []*Foo{} | 822 vals = []*Foo{} |
| 867 » » » » » » So(ds.GetAll(q, &vals), ShouldBe
Nil) | 823 » » » » » » So(ds.GetAll(c, q, &vals), Shoul
dBeNil) |
| 868 So(vals, ShouldResemble, []*Foo{
foo1, projectData[0], foo7}) | 824 So(vals, ShouldResemble, []*Foo{
foo1, projectData[0], foo7}) |
| 869 | 825 |
| 870 return nil | 826 return nil |
| 871 }, nil), ShouldBeNil) | 827 }, nil), ShouldBeNil) |
| 872 | 828 |
| 873 vals = []*Foo{} | 829 vals = []*Foo{} |
| 874 » » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 830 » » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 875 So(vals, ShouldResemble, []*Foo{foo1, pr
ojectData[0], foo7}) | 831 So(vals, ShouldResemble, []*Foo{foo1, pr
ojectData[0], foo7}) |
| 876 | 832 |
| 877 return nil | 833 return nil |
| 878 }, nil), ShouldBeNil) | 834 }, nil), ShouldBeNil) |
| 879 | 835 |
| 880 vals := []*Foo{} | 836 vals := []*Foo{} |
| 881 » » » » So(ds.GetAll(q, &vals), ShouldBeNil) | 837 » » » » So(ds.GetAll(c, q, &vals), ShouldBeNil) |
| 882 So(vals, ShouldResemble, []*Foo{foo1, projectDat
a[0], foo7}) | 838 So(vals, ShouldResemble, []*Foo{foo1, projectDat
a[0], foo7}) |
| 883 | 839 |
| 884 }) | 840 }) |
| 885 | 841 |
| 886 Convey("start transaction from inside query", func() { | 842 Convey("start transaction from inside query", func() { |
| 887 » » » » _, _, ds := mkds(projectData) | 843 » » » » _, _, c := mkds(projectData) |
| 888 » » » » So(ds.RunInTransaction(func(c context.Context) e
rror { | 844 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 889 » » » » » ds := datastore.Get(c) | 845 » » » » » q := ds.NewQuery("Foo").Ancestor(root) |
| 890 | 846 » » » » » return ds.Run(c, q, func(pm ds.PropertyM
ap) { |
| 891 » » » » » q := datastore.NewQuery("Foo").Ancestor(
root) | 847 » » » » » » So(ds.RunInTransaction(c, func(c
context.Context) error { |
| 892 » » » » » return ds.Run(q, func(pm datastore.Prope
rtyMap) { | 848 » » » » » » » pm["Value"] = append(pm.
Slice("Value"), ds.MkProperty("wat")) |
| 893 » » » » » » So(ds.RunInTransaction(func(c co
ntext.Context) error { | 849 » » » » » » » return ds.Put(c, pm) |
| 894 » » » » » » » ds := datastore.Get(c) | |
| 895 » » » » » » » pm["Value"] = append(pm.
Slice("Value"), datastore.MkProperty("wat")) | |
| 896 » » » » » » » return ds.Put(pm) | |
| 897 }, nil), ShouldBeNil) | 850 }, nil), ShouldBeNil) |
| 898 }) | 851 }) |
| 899 » » » » }, &datastore.TransactionOptions{XG: true}), Sho
uldBeNil) | 852 » » » » }, &ds.TransactionOptions{XG: true}), ShouldBeNi
l) |
| 900 | 853 |
| 901 » » » » So(ds.Run(datastore.NewQuery("Foo"), func(pm dat
astore.PropertyMap) { | 854 » » » » So(ds.Run(c, ds.NewQuery("Foo"), func(pm ds.Prop
ertyMap) { |
| 902 val := pm.Slice("Value") | 855 val := pm.Slice("Value") |
| 903 So(val[len(val)-1].Value(), ShouldResemb
le, "wat") | 856 So(val[len(val)-1].Value(), ShouldResemb
le, "wat") |
| 904 }), ShouldBeNil) | 857 }), ShouldBeNil) |
| 905 }) | 858 }) |
| 906 | 859 |
| 907 }) | 860 }) |
| 908 | 861 |
| 909 }) | 862 }) |
| 910 | 863 |
| 911 } | 864 } |
| OLD | NEW |