Skip to content

Commit 22c790f

Browse files
kulshekharflovilmart
authored andcommitted
Wrap postgres class creation in a transaction (#2958)
1 parent 0e78c28 commit 22c790f

File tree

1 file changed

+19
-9
lines changed

1 file changed

+19
-9
lines changed

src/Adapters/Storage/Postgres/PostgresStorageAdapter.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const PostgresRelationDoesNotExistError = '42P01';
44
const PostgresDuplicateRelationError = '42P07';
55
const PostgresDuplicateColumnError = '42701';
66
const PostgresUniqueIndexViolationError = '23505';
7+
const PostgresTransactionAbortedError = '25P02';
78
const logger = require('../../../logger');
89

910
const debug = function(){
@@ -385,8 +386,9 @@ export class PostgresStorageAdapter {
385386
this._client = createClient(uri, databaseOptions);
386387
}
387388

388-
_ensureSchemaCollectionExists() {
389-
return this._client.none('CREATE TABLE "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )')
389+
_ensureSchemaCollectionExists(conn) {
390+
conn = conn || this._client;
391+
return conn.none('CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )')
390392
.catch(error => {
391393
if (error.code === PostgresDuplicateRelationError || error.code === PostgresUniqueIndexViolationError) {
392394
// Table already exists, must have been created by a different request. Ignore error.
@@ -410,13 +412,20 @@ export class PostgresStorageAdapter {
410412
}
411413

412414
createClass(className, schema) {
413-
return this.createTable(className, schema).then(() => {
414-
return this._client.none('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($<className>, $<schema>, true)', { className, schema });
415+
return this._client.tx(t => {
416+
const q1 = this.createTable(className, schema, t);
417+
const q2 = t.none('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($<className>, $<schema>, true)', { className, schema });
418+
419+
return t.batch([q1, q2]);
415420
})
416421
.then(() => {
417422
return toParseSchema(schema)
418423
})
419424
.catch((err) => {
425+
if (Array.isArray(err.data) && err.data.length > 1 && err.data[0].result.code === PostgresTransactionAbortedError) {
426+
err = err.data[1].result;
427+
}
428+
420429
if (err.code === PostgresUniqueIndexViolationError && err.detail.includes(className)) {
421430
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, `Class ${className} already exists.`)
422431
}
@@ -425,7 +434,8 @@ export class PostgresStorageAdapter {
425434
}
426435

427436
// Just create a table, do not insert in schema
428-
createTable(className, schema) {
437+
createTable(className, schema, conn) {
438+
conn = conn || this._client;
429439
debug('createTable', className, schema);
430440
let valuesArray = [];
431441
let patternsArray = [];
@@ -458,10 +468,10 @@ export class PostgresStorageAdapter {
458468
}
459469
index = index+2;
460470
});
461-
const qs = `CREATE TABLE $1:name (${patternsArray.join(',')})`;
471+
const qs = `CREATE TABLE IF NOT EXISTS $1:name (${patternsArray.join(',')})`;
462472
const values = [className, ...valuesArray];
463-
return this._ensureSchemaCollectionExists()
464-
.then(() => this._client.none(qs, values))
473+
return this._ensureSchemaCollectionExists(conn)
474+
.then(() => conn.none(qs, values))
465475
.catch(error => {
466476
if (error.code === PostgresDuplicateRelationError) {
467477
// Table already exists, must have been created by a different request. Ignore error.
@@ -471,7 +481,7 @@ export class PostgresStorageAdapter {
471481
}).then(() => {
472482
// Create the relation tables
473483
return Promise.all(relations.map((fieldName) => {
474-
return this._client.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {joinTable: `_Join:${fieldName}:${className}`});
484+
return conn.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {joinTable: `_Join:${fieldName}:${className}`});
475485
}));
476486
});
477487
}

0 commit comments

Comments
 (0)