From 4d1a2c5373d4a1573f1eefb5c4e182e14e3b2b3d Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Mon, 20 Jul 2015 12:41:43 -0700 Subject: [PATCH] fix(database): Incorrectly creating join insert queries for exactly 200 objects --- spec-nylas/stores/database-store-spec.coffee | 39 ++++++++++++++++++++ src/flux/stores/database-store.coffee | 6 ++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/spec-nylas/stores/database-store-spec.coffee b/spec-nylas/stores/database-store-spec.coffee index 733bb9e21..d7c66208a 100644 --- a/spec-nylas/stores/database-store-spec.coffee +++ b/spec-nylas/stores/database-store-spec.coffee @@ -196,6 +196,45 @@ describe "DatabaseStore", -> expect(@performed[2].query).toBe('INSERT OR IGNORE INTO `TestModel-Label` (`id`, `value`) VALUES (?,?),(?,?)') expect(@performed[2].values).toEqual(['local-6806434c-b0cd', 'a','local-6806434c-b0cd', 'b']) + describe "model collection attributes query building", -> + beforeEach -> + TestModel.configureWithCollectionAttribute() + @m = new TestModel(id: 'local-6806434c-b0cd') + @m.labels = [] + + it "should page association records into multiple queries correctly", -> + @m.labels.push(new Label(id: "id-#{i}")) for i in [0..199] + DatabaseStore._writeModels([@m]) + + collectionAttributeQueries = _.filter @performed, (i) -> + i.query.indexOf('INSERT OR IGNORE INTO `TestModel-Label`') == 0 + + expect(collectionAttributeQueries.length).toBe(1) + expect(collectionAttributeQueries[0].values[399]).toEqual('id-199') + + it "should page association records into multiple queries correctly", -> + @m.labels.push(new Label(id: "id-#{i}")) for i in [0..200] + DatabaseStore._writeModels([@m]) + + collectionAttributeQueries = _.filter @performed, (i) -> + i.query.indexOf('INSERT OR IGNORE INTO `TestModel-Label`') == 0 + + expect(collectionAttributeQueries.length).toBe(2) + expect(collectionAttributeQueries[0].values[399]).toEqual('id-199') + expect(collectionAttributeQueries[1].values[1]).toEqual('id-200') + + it "should page association records into multiple queries correctly", -> + @m.labels.push(new Label(id: "id-#{i}")) for i in [0..201] + DatabaseStore._writeModels([@m]) + + collectionAttributeQueries = _.filter @performed, (i) -> + i.query.indexOf('INSERT OR IGNORE INTO `TestModel-Label`') == 0 + + expect(collectionAttributeQueries.length).toBe(2) + expect(collectionAttributeQueries[0].values[399]).toEqual('id-199') + expect(collectionAttributeQueries[1].values[1]).toEqual('id-200') + expect(collectionAttributeQueries[1].values[3]).toEqual('id-201') + describe "when the model has joined data attributes", -> beforeEach -> TestModel.configureWithJoinedDataAttribute() diff --git a/src/flux/stores/database-store.coffee b/src/flux/stores/database-store.coffee index 61c7aa0da..601dd862f 100644 --- a/src/flux/stores/database-store.coffee +++ b/src/flux/stores/database-store.coffee @@ -448,7 +448,11 @@ class DatabaseStore extends NylasStore unless joinedValues.length is 0 # Write no more than 200 items (400 values) at once to avoid sqlite limits - for slice in [0..Math.floor(joinedValues.length / 400)] by 1 + # 399 values: slices:[0..0] + # 400 values: slices:[0..0] + # 401 values: slices:[0..1] + slicePageCount = Math.ceil(joinedValues.length / 400) - 1 + for slice in [0..slicePageCount] by 1 [ms, me] = [slice*200, slice*200 + 199] [vs, ve] = [slice*400, slice*400 + 399] promises.push @_query("INSERT OR IGNORE INTO `#{joinTable}` (`id`, `value`) VALUES #{joinMarks[ms..me].join(',')}", joinedValues[vs..ve])