From 4c7be1004f28edb6c64790891f91678241b4d759 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Thu, 16 Jun 2016 19:06:02 -0700 Subject: [PATCH 1/3] Support pointers in postgres --- spec/ParseObject.spec.js | 2 +- spec/PurchaseValidation.spec.js | 3 +-- spec/helper.js | 2 +- src/Adapters/Storage/Postgres/PostgresStorageAdapter.js | 4 ++++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/ParseObject.spec.js b/spec/ParseObject.spec.js index 81ae2c3844..c388c32a71 100644 --- a/spec/ParseObject.spec.js +++ b/spec/ParseObject.spec.js @@ -49,7 +49,7 @@ describe('Parse.Object testing', () => { }); }); - it_exclude_dbs(['postgres'])("save cycle", function(done) { + it("save cycle", done => { var a = new Parse.Object("TestObject"); var b = new Parse.Object("TestObject"); a.set("b", b); diff --git a/spec/PurchaseValidation.spec.js b/spec/PurchaseValidation.spec.js index cfd776d234..384a6665e2 100644 --- a/spec/PurchaseValidation.spec.js +++ b/spec/PurchaseValidation.spec.js @@ -135,8 +135,7 @@ describe("test validate_receipt endpoint", () => { }); }); - it("should fail at appstore validation", (done) => { - + it("should fail at appstore validation", done => { request.post({ headers: { 'X-Parse-Application-Id': 'test', diff --git a/spec/helper.js b/spec/helper.js index 3880caae5f..d22983e621 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -1,7 +1,7 @@ "use strict" // Sets up a Parse API server for testing. -jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 3000; +jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 5000; var cache = require('../src/cache').default; var DatabaseAdapter = require('../src/DatabaseAdapter'); diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index ec96ea0fb1..b61ac33c26 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -329,6 +329,10 @@ export class PostgresStorageAdapter { updatePatterns.push(`$${index}:name = $${index + 1}`); values.push(fieldName, fieldValue); index += 2; + } else if (fieldValue.__type === 'Pointer') { + updatePatterns.push(`$${index}:name = $${index + 1}`); + values.push(fieldName, fieldValue.objectId); + index += 2; } else { return Promise.reject(new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, `Postgres doesn't support update ${JSON.stringify(fieldValue)} yet`)); } From 8850369bb2e6a88c74268944aac7a26ffcfdd395 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Fri, 17 Jun 2016 09:55:17 -0700 Subject: [PATCH 2/3] implement count --- spec/InstallationsRouter.spec.js | 8 ++++++-- spec/ParseObject.spec.js | 2 +- .../Storage/Postgres/PostgresStorageAdapter.js | 14 ++++++++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/spec/InstallationsRouter.spec.js b/spec/InstallationsRouter.spec.js index f147a83cf6..a318ec5a73 100644 --- a/spec/InstallationsRouter.spec.js +++ b/spec/InstallationsRouter.spec.js @@ -103,7 +103,7 @@ describe('InstallationsRouter', () => { }); }); - it_exclude_dbs(['postgres'])('query installations with count = 1', (done) => { + it('query installations with count = 1', done => { var androidDeviceRequest = { 'installationId': '12345678-abcd-abcd-abcd-123456789abc', 'deviceType': 'android' @@ -130,7 +130,11 @@ describe('InstallationsRouter', () => { expect(response.results.length).toEqual(2); expect(response.count).toEqual(2); done(); - }); + }) + .catch(error => { + fail(JSON.stringify(error)); + done(); + }) }); it_exclude_dbs(['postgres'])('query installations with limit = 0 and count = 1', (done) => { diff --git a/spec/ParseObject.spec.js b/spec/ParseObject.spec.js index c388c32a71..cb57e87233 100644 --- a/spec/ParseObject.spec.js +++ b/spec/ParseObject.spec.js @@ -1478,7 +1478,7 @@ describe('Parse.Object testing', () => { expectError(Parse.Error.MISSING_OBJECT_ID, done)); }); - it("fetchAll error on deleted object", function(done) { + it_exclude_dbs(['postgres'])("fetchAll error on deleted object", function(done) { var numItems = 11; var container = new Container(); var subContainer = new Container(); diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index b61ac33c26..a327e0e10a 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -356,7 +356,10 @@ export class PostgresStorageAdapter { let where = buildWhereClause({ schema, query, index: 2 }) values.push(...where.values); - const qs = `SELECT * FROM $1:name WHERE ${where.pattern} ${limit !== undefined ? `LIMIT $${values.length + 1}` : ''}`; + const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + const limitPattern = limit !== undefined ? `LIMIT $${values.length + 1}` : ''; + + const qs = `SELECT * FROM $1:name ${wherePattern} ${limitPattern}`; if (limit !== undefined) { values.push(limit); } @@ -412,7 +415,14 @@ export class PostgresStorageAdapter { // Executes a count. count(className, schema, query) { - return Promise.reject('Not implemented yet.') + let values = [className]; + let where = buildWhereClause({ schema, query, index: 2 }); + values.push(...where.values); + + const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; + const qs = `SELECT COUNT(*) FROM $1:name ${wherePattern}`; + return this._client.query(qs, values) + .then(result => parseInt(result[0].count)) } } From e9d3e7a1637b9ad9a0bdba077b3ffb7f35a48adf Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Fri, 17 Jun 2016 10:52:39 -0700 Subject: [PATCH 3/3] Fix bug in createClass --- spec/InstallationsRouter.spec.js | 2 +- .../Storage/Postgres/PostgresStorageAdapter.js | 3 ++- src/Controllers/SchemaController.js | 14 ++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/spec/InstallationsRouter.spec.js b/spec/InstallationsRouter.spec.js index a318ec5a73..46ac51efbc 100644 --- a/spec/InstallationsRouter.spec.js +++ b/spec/InstallationsRouter.spec.js @@ -137,7 +137,7 @@ describe('InstallationsRouter', () => { }) }); - it_exclude_dbs(['postgres'])('query installations with limit = 0 and count = 1', (done) => { + it('query installations with limit = 0 and count = 1', (done) => { var androidDeviceRequest = { 'installationId': '12345678-abcd-abcd-abcd-123456789abc', 'deviceType': 'android' diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index a327e0e10a..f449e20f68 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -133,6 +133,7 @@ export class PostgresStorageAdapter { } }) .then(() => this._client.query('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($, $, true)', { className, schema })) + .then(() => schema); } addFieldIfNotExists(className, fieldName, type) { @@ -212,7 +213,7 @@ export class PostgresStorageAdapter { // rejection reason are TBD. getAllClasses() { return this._ensureSchemaCollectionExists() - .then(() => this._client.map('SELECT * FROM "_SCHEMA"'), null, row => ({ className: row.className, ...row.schema })); + .then(() => this._client.map('SELECT * FROM "_SCHEMA"', null, row => ({ className: row.className, ...row.schema }))); } // Return a promise for the schema with the given name, in Parse format. If diff --git a/src/Controllers/SchemaController.js b/src/Controllers/SchemaController.js index e85421f90b..2700df8085 100644 --- a/src/Controllers/SchemaController.js +++ b/src/Controllers/SchemaController.js @@ -408,23 +408,25 @@ class SchemaController { return Promise.resolve(this); } // We don't have this class. Update the schema - return this.addClassIfNotExists(className).then(() => { - // The schema update succeeded. Reload the schema - return this.reloadData(); - }, error => { + return this.addClassIfNotExists(className) + // The schema update succeeded. Reload the schema + .then(() => this.reloadData()) + .catch(error => { // The schema update failed. This can be okay - it might // have failed because there's a race condition and a different // client is making the exact same schema update that we want. // So just reload the schema. return this.reloadData(); - }).then(() => { + }) + .then(() => { // Ensure that the schema now validates if (this.data[className]) { return this; } else { throw new Parse.Error(Parse.Error.INVALID_JSON, `Failed to add ${className}`); } - }, error => { + }) + .catch(error => { // The schema still doesn't validate. Give up throw new Parse.Error(Parse.Error.INVALID_JSON, 'schema class name does not revalidate'); });