Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update PostgresStorageAdapter.js #6275

Merged
merged 4 commits into from
Dec 16, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 46 additions & 44 deletions src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -829,9 +829,9 @@ export class PostgresStorageAdapter implements StorageAdapter {
this._client.$pool.end();
}

_ensureSchemaCollectionExists(conn: any) {
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") )'
)
Expand All @@ -848,17 +848,17 @@ 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],
a => a.exists
);
}

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,
Expand All @@ -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 = {},
Expand Down Expand Up @@ -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);
}
Expand All @@ -932,16 +932,16 @@ 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 => {
.tx('create-class', async t => {
const q1 = this.createTable(className, schema, t);
const q2 = t.none(
'INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($<className>, $<schema>, true)',
Expand All @@ -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(() => {
Expand All @@ -977,7 +979,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);
Expand Down Expand Up @@ -1042,12 +1044,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>',
{ className },
Expand All @@ -1068,7 +1070,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
});
}

addFieldIfNotExists(
async addFieldIfNotExists(
className: string,
fieldName: string,
type: any,
Expand All @@ -1078,7 +1080,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(
Expand All @@ -1091,7 +1093,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
);
} catch (error) {
if (error.code === PostgresRelationDoesNotExistError) {
return await self.createClass(
return self.createClass(
className,
{ fields: { [fieldName]: type } },
t
Expand Down Expand Up @@ -1128,7 +1130,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] },
{
Expand All @@ -1142,12 +1144,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"');
Expand Down Expand Up @@ -1196,7 +1198,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
// may do so.

// Returns a Promise.
deleteFields(
async deleteFields(
className: string,
schema: SchemaType,
fieldNames: string[]
Expand All @@ -1218,9 +1220,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"=$<schema> WHERE "className"=$<className>',
'UPDATE "_SCHEMA" SET "schema" = $<schema> WHERE "className" = $<className>',
{ schema, className }
);
if (values.length > 1) {
Expand All @@ -1232,7 +1234,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);
Expand All @@ -1245,10 +1247,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"=$<className>', {
.any('SELECT * FROM "_SCHEMA" WHERE "className" = $<className>', {
className,
})
.then(result => {
Expand All @@ -1261,7 +1263,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,
Expand Down Expand Up @@ -1426,7 +1428,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,
Expand Down Expand Up @@ -1469,7 +1471,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
return promise;
}
// Return value not currently well specified.
findOneAndUpdate(
async findOneAndUpdate(
className: string,
schema: SchemaType,
query: QueryType,
Expand All @@ -1487,7 +1489,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,
Expand Down Expand Up @@ -1980,7 +1982,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[]
Expand Down Expand Up @@ -2016,7 +2018,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
}

// Executes a count.
count(
async count(
className: string,
schema: SchemaType,
query: QueryType,
Expand Down Expand Up @@ -2055,7 +2057,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
});
}

distinct(
async distinct(
className: string,
schema: SchemaType,
query: QueryType,
Expand Down Expand Up @@ -2121,7 +2123,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;
Expand Down Expand Up @@ -2323,7 +2325,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 => {
Expand Down Expand Up @@ -2362,7 +2364,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
});
}

createIndexes(className: string, indexes: any, conn: ?any): Promise<void> {
async createIndexes(className: string, indexes: any, conn: ?any): Promise<void> {
return (conn || this._client).tx(t =>
t.batch(
indexes.map(i => {
Expand All @@ -2376,43 +2378,43 @@ export class PostgresStorageAdapter implements StorageAdapter {
);
}

createIndexesIfNeeded(
async createIndexesIfNeeded(
className: string,
fieldName: string,
type: any,
conn: ?any
): Promise<void> {
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<void> {
async dropIndexes(className: string, indexes: any, conn: any): Promise<void> {
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<void> {
async updateSchemaWithIndexes(): Promise<void> {
return Promise.resolve();
}

// Used for testing purposes
updateEstimatedCount(className: string) {
async updateEstimatedCount(className: string) {
return this._client.none('ANALYZE $1:name', [className]);
}

createTransactionalSession(): Promise<any> {
async createTransactionalSession(): Promise<any> {
return new Promise(resolve => {
const transactionalSession = {};
transactionalSession.result = this._client.tx(t => {
Expand Down