diff --git a/.travis.yml b/.travis.yml index 06b1995fe1..96240807de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: node_js +dist: trusty +sudo: required node_js: - '4.5' - '6.1' @@ -6,7 +8,7 @@ services: - postgresql - redis-server addons: - postgresql: '9.4' + postgresql: '9.5' before_script: - ls -al "$HOME/.mongodb/versions" - psql -c 'create database parse_server_postgres_adapter_test_database;' -U postgres diff --git a/spec/RestCreate.spec.js b/spec/RestCreate.spec.js index 893952313f..ce553ea369 100644 --- a/spec/RestCreate.spec.js +++ b/spec/RestCreate.spec.js @@ -52,7 +52,7 @@ describe('rest create', () => { }); }); - it_exclude_dbs(['postgres'])('handles object and subdocument', done => { + it('handles object and subdocument', done => { let obj = { subdoc: {foo: 'bar', wu: 'tan'} }; rest.create(config, auth.nobody(config), 'MyClass', obj) .then(() => database.adapter.find('MyClass', { fields: {} }, {}, {})) diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index fcc9a4c77f..5870e33502 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -810,6 +810,7 @@ export class PostgresStorageAdapter { let index = 2; schema = toPostgresSchema(schema); + const originalUpdate = {...update}; update = handleDotFields(update); // Resolve authData first, // So we don't end up with multiple key updates @@ -914,9 +915,19 @@ export class PostgresStorageAdapter { } else if (typeof fieldValue === 'object' && schema.fields[fieldName] && schema.fields[fieldName].type === 'Object') { - updatePatterns.push(`$${index}:name = $${index + 1}`); - values.push(fieldName, fieldValue); - index += 2; + const keysToDelete = Object.keys(originalUpdate).filter(k => { + // choose top level fields that have a delete operation set + return originalUpdate[k].__op === 'Delete' && k.split('.').length === 2 + }).map(k => k.split('.')[1]); + + const deletePatterns = keysToDelete.reduce((p, c, i) => { + return p + ` - '$${index + 1 + i}:value'`; + }, ''); + + updatePatterns.push(`$${index}:name = ( COALESCE($${index}:name, '{}'::jsonb) ${deletePatterns} || $${index + 1 + keysToDelete.length}::jsonb )`); + + values.push(fieldName, ...keysToDelete, JSON.stringify(fieldValue)); + index += 2 + keysToDelete.length; } else if (Array.isArray(fieldValue) && schema.fields[fieldName] && schema.fields[fieldName].type === 'Array') {