Implement pointer types in postgres. (#2086)

* Support pointers in postgres

* implement count

* Fix bug in createClass
This commit is contained in:
Drew
2016-06-17 11:09:42 -07:00
committed by GitHub
parent ab06055369
commit 006540cda5
6 changed files with 37 additions and 17 deletions

View File

@@ -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 = { var androidDeviceRequest = {
'installationId': '12345678-abcd-abcd-abcd-123456789abc', 'installationId': '12345678-abcd-abcd-abcd-123456789abc',
'deviceType': 'android' 'deviceType': 'android'
@@ -130,10 +130,14 @@ describe('InstallationsRouter', () => {
expect(response.results.length).toEqual(2); expect(response.results.length).toEqual(2);
expect(response.count).toEqual(2); expect(response.count).toEqual(2);
done(); done();
}); })
.catch(error => {
fail(JSON.stringify(error));
done();
})
}); });
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 = { var androidDeviceRequest = {
'installationId': '12345678-abcd-abcd-abcd-123456789abc', 'installationId': '12345678-abcd-abcd-abcd-123456789abc',
'deviceType': 'android' 'deviceType': 'android'

View File

@@ -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 a = new Parse.Object("TestObject");
var b = new Parse.Object("TestObject"); var b = new Parse.Object("TestObject");
a.set("b", b); a.set("b", b);
@@ -1478,7 +1478,7 @@ describe('Parse.Object testing', () => {
expectError(Parse.Error.MISSING_OBJECT_ID, done)); 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 numItems = 11;
var container = new Container(); var container = new Container();
var subContainer = new Container(); var subContainer = new Container();

View File

@@ -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({ request.post({
headers: { headers: {
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',

View File

@@ -1,7 +1,7 @@
"use strict" "use strict"
// Sets up a Parse API server for testing. // 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 cache = require('../src/cache').default;
var DatabaseAdapter = require('../src/DatabaseAdapter'); var DatabaseAdapter = require('../src/DatabaseAdapter');

View File

@@ -133,6 +133,7 @@ export class PostgresStorageAdapter {
} }
}) })
.then(() => this._client.query('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($<className>, $<schema>, true)', { className, schema })) .then(() => this._client.query('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($<className>, $<schema>, true)', { className, schema }))
.then(() => schema);
} }
addFieldIfNotExists(className, fieldName, type) { addFieldIfNotExists(className, fieldName, type) {
@@ -212,7 +213,7 @@ export class PostgresStorageAdapter {
// rejection reason are TBD. // rejection reason are TBD.
getAllClasses() { getAllClasses() {
return this._ensureSchemaCollectionExists() 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 // Return a promise for the schema with the given name, in Parse format. If
@@ -329,6 +330,10 @@ export class PostgresStorageAdapter {
updatePatterns.push(`$${index}:name = $${index + 1}`); updatePatterns.push(`$${index}:name = $${index + 1}`);
values.push(fieldName, fieldValue); values.push(fieldName, fieldValue);
index += 2; index += 2;
} else if (fieldValue.__type === 'Pointer') {
updatePatterns.push(`$${index}:name = $${index + 1}`);
values.push(fieldName, fieldValue.objectId);
index += 2;
} else { } else {
return Promise.reject(new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, `Postgres doesn't support update ${JSON.stringify(fieldValue)} yet`)); return Promise.reject(new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, `Postgres doesn't support update ${JSON.stringify(fieldValue)} yet`));
} }
@@ -352,7 +357,10 @@ export class PostgresStorageAdapter {
let where = buildWhereClause({ schema, query, index: 2 }) let where = buildWhereClause({ schema, query, index: 2 })
values.push(...where.values); 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) { if (limit !== undefined) {
values.push(limit); values.push(limit);
} }
@@ -408,7 +416,14 @@ export class PostgresStorageAdapter {
// Executes a count. // Executes a count.
count(className, schema, query) { 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))
} }
} }

View File

@@ -408,23 +408,25 @@ class SchemaController {
return Promise.resolve(this); return Promise.resolve(this);
} }
// We don't have this class. Update the schema // We don't have this class. Update the schema
return this.addClassIfNotExists(className).then(() => { return this.addClassIfNotExists(className)
// The schema update succeeded. Reload the schema // The schema update succeeded. Reload the schema
return this.reloadData(); .then(() => this.reloadData())
}, error => { .catch(error => {
// The schema update failed. This can be okay - it might // The schema update failed. This can be okay - it might
// have failed because there's a race condition and a different // have failed because there's a race condition and a different
// client is making the exact same schema update that we want. // client is making the exact same schema update that we want.
// So just reload the schema. // So just reload the schema.
return this.reloadData(); return this.reloadData();
}).then(() => { })
.then(() => {
// Ensure that the schema now validates // Ensure that the schema now validates
if (this.data[className]) { if (this.data[className]) {
return this; return this;
} else { } else {
throw new Parse.Error(Parse.Error.INVALID_JSON, `Failed to add ${className}`); throw new Parse.Error(Parse.Error.INVALID_JSON, `Failed to add ${className}`);
} }
}, error => { })
.catch(error => {
// The schema still doesn't validate. Give up // The schema still doesn't validate. Give up
throw new Parse.Error(Parse.Error.INVALID_JSON, 'schema class name does not revalidate'); throw new Parse.Error(Parse.Error.INVALID_JSON, 'schema class name does not revalidate');
}); });