From 6af020213e127112b45f793f1ef192486f82c0dd Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Wed, 11 Dec 2019 21:01:48 +0000 Subject: [PATCH 1/4] Update PostgresStorageAdapter.js Improving use of the `await.async` notation in relation to `pg-promise`, and in general. --- .../Postgres/PostgresStorageAdapter.js | 95 +++++++++---------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index 60aa4c1442..89b7a47dff 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -829,7 +829,7 @@ export class PostgresStorageAdapter implements StorageAdapter { this._client.$pool.end(); } - _ensureSchemaCollectionExists(conn: any) { + async _ensureSchemaCollectionExists(conn: any) { conn = conn || this._client; return conn .none( @@ -848,7 +848,7 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - classExists(name: string) { + async classExists(name: string) { return this._client.one( 'SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1)', [name], @@ -856,9 +856,9 @@ export class PostgresStorageAdapter implements StorageAdapter { ); } - setClassLevelPermissions(className: string, CLPs: any) { + async setClassLevelPermissions(className: string, CLPs: any) { const self = this; - return this._client.task('set-class-level-permissions', async t => { + await this._client.task('set-class-level-permissions', async t => { await self._ensureSchemaCollectionExists(t); const values = [ className, @@ -867,13 +867,13 @@ export class PostgresStorageAdapter implements StorageAdapter { JSON.stringify(CLPs), ]; await t.none( - `UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className"=$1`, + `UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className" = $1`, values ); }); } - setIndexesWithSchemaFormat( + async setIndexesWithSchemaFormat( className: string, submittedIndexes: any, existingIndexes: any = {}, @@ -923,7 +923,7 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } }); - return conn.tx('set-indexes-with-schema-format', async t => { + await conn.tx('set-indexes-with-schema-format', async t => { if (insertedIndexes.length > 0) { await self.createIndexes(className, insertedIndexes, t); } @@ -932,29 +932,28 @@ export class PostgresStorageAdapter implements StorageAdapter { } await self._ensureSchemaCollectionExists(t); await t.none( - 'UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className"=$1', + 'UPDATE "_SCHEMA" SET $2:name = json_object_set_key($2:name, $3::text, $4::jsonb) WHERE "className" = $1', [className, 'schema', 'indexes', JSON.stringify(existingIndexes)] ); }); } - createClass(className: string, schema: SchemaType, conn: ?any) { + async createClass(className: string, schema: SchemaType, conn: ?any) { conn = conn || this._client; - return conn - .tx('create-class', t => { - const q1 = this.createTable(className, schema, t); - const q2 = t.none( + await conn + .tx('create-class', async t => { + await this.createTable(className, schema, t); + await t.none( 'INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($, $, true)', { className, schema } ); - const q3 = this.setIndexesWithSchemaFormat( + await this.setIndexesWithSchemaFormat( className, schema.indexes, {}, schema.fields, t ); - return t.batch([q1, q2, q3]); }) .then(() => { return toParseSchema(schema); @@ -977,7 +976,7 @@ export class PostgresStorageAdapter implements StorageAdapter { } // Just create a table, do not insert in schema - createTable(className: string, schema: SchemaType, conn: any) { + async createTable(className: string, schema: SchemaType, conn: any) { conn = conn || this._client; const self = this; debug('createTable', className, schema); @@ -1042,12 +1041,12 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - schemaUpgrade(className: string, schema: SchemaType, conn: any) { + async schemaUpgrade(className: string, schema: SchemaType, conn: any) { debug('schemaUpgrade', { className, schema }); conn = conn || this._client; const self = this; - return conn.tx('schema-upgrade', async t => { + await conn.tx('schema-upgrade', async t => { const columns = await t.map( 'SELECT column_name FROM information_schema.columns WHERE table_name = $', { className }, @@ -1068,7 +1067,7 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - addFieldIfNotExists( + async addFieldIfNotExists( className: string, fieldName: string, type: any, @@ -1078,7 +1077,7 @@ export class PostgresStorageAdapter implements StorageAdapter { debug('addFieldIfNotExists', { className, fieldName, type }); conn = conn || this._client; const self = this; - return conn.tx('add-field-if-not-exists', async t => { + await conn.tx('add-field-if-not-exists', async t => { if (type.type !== 'Relation') { try { await t.none( @@ -1091,7 +1090,7 @@ export class PostgresStorageAdapter implements StorageAdapter { ); } catch (error) { if (error.code === PostgresRelationDoesNotExistError) { - return await self.createClass( + return self.createClass( className, { fields: { [fieldName]: type } }, t @@ -1128,7 +1127,7 @@ export class PostgresStorageAdapter implements StorageAdapter { // Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.) // and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible. - deleteClass(className: string) { + async deleteClass(className: string) { const operations = [ { query: `DROP TABLE IF EXISTS $1:name`, values: [className] }, { @@ -1142,12 +1141,12 @@ export class PostgresStorageAdapter implements StorageAdapter { } // Delete all data known to this adapter. Used for testing. - deleteAllClasses() { + async deleteAllClasses() { const now = new Date().getTime(); const helpers = this._pgp.helpers; debug('deleteAllClasses'); - return this._client + await this._client .task('delete-all-classes', async t => { try { const results = await t.any('SELECT * FROM "_SCHEMA"'); @@ -1196,7 +1195,7 @@ export class PostgresStorageAdapter implements StorageAdapter { // may do so. // Returns a Promise. - deleteFields( + async deleteFields( className: string, schema: SchemaType, fieldNames: string[] @@ -1218,9 +1217,9 @@ export class PostgresStorageAdapter implements StorageAdapter { }) .join(', DROP COLUMN'); - return this._client.tx('delete-fields', async t => { + await this._client.tx('delete-fields', async t => { await t.none( - 'UPDATE "_SCHEMA" SET "schema"=$ WHERE "className"=$', + 'UPDATE "_SCHEMA" SET "schema" = $ WHERE "className" = $', { schema, className } ); if (values.length > 1) { @@ -1232,7 +1231,7 @@ export class PostgresStorageAdapter implements StorageAdapter { // Return a promise for all schemas known to this adapter, in Parse format. In case the // schemas cannot be retrieved, returns a promise that rejects. Requirements for the // rejection reason are TBD. - getAllClasses() { + async getAllClasses() { const self = this; return this._client.task('get-all-classes', async t => { await self._ensureSchemaCollectionExists(t); @@ -1245,10 +1244,10 @@ export class PostgresStorageAdapter implements StorageAdapter { // Return a promise for the schema with the given name, in Parse format. If // this adapter doesn't know about the schema, return a promise that rejects with // undefined as the reason. - getClass(className: string) { + async getClass(className: string) { debug('getClass', className); return this._client - .any('SELECT * FROM "_SCHEMA" WHERE "className"=$', { + .any('SELECT * FROM "_SCHEMA" WHERE "className" = $', { className, }) .then(result => { @@ -1261,7 +1260,7 @@ export class PostgresStorageAdapter implements StorageAdapter { } // TODO: remove the mongo format dependency in the return value - createObject( + async createObject( className: string, schema: SchemaType, object: any, @@ -1426,7 +1425,7 @@ export class PostgresStorageAdapter implements StorageAdapter { // Remove all objects that match the given Parse Query. // If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined. // If there is some other error, reject with INTERNAL_SERVER_ERROR. - deleteObjectsByQuery( + async deleteObjectsByQuery( className: string, schema: SchemaType, query: QueryType, @@ -1469,7 +1468,7 @@ export class PostgresStorageAdapter implements StorageAdapter { return promise; } // Return value not currently well specified. - findOneAndUpdate( + async findOneAndUpdate( className: string, schema: SchemaType, query: QueryType, @@ -1487,7 +1486,7 @@ export class PostgresStorageAdapter implements StorageAdapter { } // Apply the update to all objects that match the given Parse Query. - updateObjectsByQuery( + async updateObjectsByQuery( className: string, schema: SchemaType, query: QueryType, @@ -1980,7 +1979,7 @@ export class PostgresStorageAdapter implements StorageAdapter { // As such, we shouldn't expose this function to users of parse until we have an out-of-band // Way of determining if a field is nullable. Undefined doesn't count against uniqueness, // which is why we use sparse indexes. - ensureUniqueness( + async ensureUniqueness( className: string, schema: SchemaType, fieldNames: string[] @@ -2016,7 +2015,7 @@ export class PostgresStorageAdapter implements StorageAdapter { } // Executes a count. - count( + async count( className: string, schema: SchemaType, query: QueryType, @@ -2055,7 +2054,7 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - distinct( + async distinct( className: string, schema: SchemaType, query: QueryType, @@ -2121,7 +2120,7 @@ export class PostgresStorageAdapter implements StorageAdapter { ); } - aggregate(className: string, schema: any, pipeline: any) { + async aggregate(className: string, schema: any, pipeline: any) { debug('aggregate', className, pipeline); const values = [className]; let index: number = 2; @@ -2323,7 +2322,7 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - performInitialization({ VolatileClassesSchemas }: any) { + async performInitialization({ VolatileClassesSchemas }: any) { // TODO: This method needs to be rewritten to make proper use of connections (@vitaly-t) debug('performInitialization'); const promises = VolatileClassesSchemas.map(schema => { @@ -2362,7 +2361,7 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - createIndexes(className: string, indexes: any, conn: ?any): Promise { + async createIndexes(className: string, indexes: any, conn: ?any): Promise { return (conn || this._client).tx(t => t.batch( indexes.map(i => { @@ -2376,43 +2375,43 @@ export class PostgresStorageAdapter implements StorageAdapter { ); } - createIndexesIfNeeded( + async createIndexesIfNeeded( className: string, fieldName: string, type: any, conn: ?any ): Promise { - return (conn || this._client).none( + await (conn || this._client).none( 'CREATE INDEX $1:name ON $2:name ($3:name)', [fieldName, className, type] ); } - dropIndexes(className: string, indexes: any, conn: any): Promise { + async dropIndexes(className: string, indexes: any, conn: any): Promise { const queries = indexes.map(i => ({ query: 'DROP INDEX $1:name', values: i, })); - return (conn || this._client).tx(t => + await (conn || this._client).tx(t => t.none(this._pgp.helpers.concat(queries)) ); } - getIndexes(className: string) { + async getIndexes(className: string) { const qs = 'SELECT * FROM pg_indexes WHERE tablename = ${className}'; return this._client.any(qs, { className }); } - updateSchemaWithIndexes(): Promise { + async updateSchemaWithIndexes(): Promise { return Promise.resolve(); } // Used for testing purposes - updateEstimatedCount(className: string) { + async updateEstimatedCount(className: string) { return this._client.none('ANALYZE $1:name', [className]); } - createTransactionalSession(): Promise { + async createTransactionalSession(): Promise { return new Promise(resolve => { const transactionalSession = {}; transactionalSession.result = this._client.tx(t => { From 8cb19c87afe3a07e93988f75e506adf5d09e06c4 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Wed, 11 Dec 2019 21:03:10 +0000 Subject: [PATCH 2/4] Update PostgresStorageAdapter.js --- src/Adapters/Storage/Postgres/PostgresStorageAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index 89b7a47dff..136260f589 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -831,7 +831,7 @@ export class PostgresStorageAdapter implements StorageAdapter { async _ensureSchemaCollectionExists(conn: any) { conn = conn || this._client; - return conn + await conn .none( 'CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )' ) From 4a66ea111e4186741d0fd111073452351ddbf95e Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Wed, 11 Dec 2019 21:26:53 +0000 Subject: [PATCH 3/4] Update PostgresStorageAdapter.js Correcting some results. --- .../Storage/Postgres/PostgresStorageAdapter.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index 136260f589..07dae99aed 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -831,7 +831,7 @@ export class PostgresStorageAdapter implements StorageAdapter { async _ensureSchemaCollectionExists(conn: any) { conn = conn || this._client; - await conn + return conn .none( 'CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )' ) @@ -940,20 +940,21 @@ export class PostgresStorageAdapter implements StorageAdapter { async createClass(className: string, schema: SchemaType, conn: ?any) { conn = conn || this._client; - await conn + return conn .tx('create-class', async t => { - await this.createTable(className, schema, t); - await t.none( + const q1 = this.createTable(className, schema, t); + const q2 = t.none( 'INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($, $, true)', { className, schema } ); - await this.setIndexesWithSchemaFormat( + const q3 = this.setIndexesWithSchemaFormat( className, schema.indexes, {}, schema.fields, t ); + return t.batch([q1, q2, q3]); }) .then(() => { return toParseSchema(schema); From 7d6adfde391796b25bca5e6419c1edbbe50c8a29 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Wed, 11 Dec 2019 21:41:49 +0000 Subject: [PATCH 4/4] Update PostgresStorageAdapter.js --- src/Adapters/Storage/Postgres/PostgresStorageAdapter.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index 07dae99aed..2ce4d92f48 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -831,7 +831,7 @@ export class PostgresStorageAdapter implements StorageAdapter { async _ensureSchemaCollectionExists(conn: any) { conn = conn || this._client; - return conn + await conn .none( 'CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )' ) @@ -954,6 +954,8 @@ export class PostgresStorageAdapter implements StorageAdapter { schema.fields, t ); + // TODO: The test should not verify the returned value, and then + // the method can be simplified, to avoid returning useless stuff. return t.batch([q1, q2, q3]); }) .then(() => {