diff --git a/spec/ParseQuery.spec.js b/spec/ParseQuery.spec.js index 230104f1..f3803b16 100644 --- a/spec/ParseQuery.spec.js +++ b/spec/ParseQuery.spec.js @@ -4589,4 +4589,28 @@ describe('Parse.Query testing', () => { const results = await query.find(); equal(results[0].get('array'), data2); }); + + it('can update mixed array', async () => { + const data1 = [0, 1.1, 'hello world', { foo: 'bar' }]; + const data2 = [0, 1, { foo: 'bar' }, [], [1, 2, 'bar']]; + const obj1 = new TestObject(); + obj1.set('array', data1); + await obj1.save(); + equal(obj1.get('array'), data1); + + const query = new Parse.Query(TestObject); + query.equalTo('objectId', obj1.id); + + const result = await query.first(); + equal(result.get('array'), data1); + + result.set('array', data2); + equal(result.get('array'), data2); + + await result.save(); + equal(result.get('array'), data2); + + const results = await query.find(); + equal(results[0].get('array'), data2); + }); }); diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index ca3b8b28..8df3acc9 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -1650,24 +1650,37 @@ export class PostgresStorageAdapter implements StorageAdapter { const expectedType = parseTypeToPostgresType(schema.fields[fieldName]); if (expectedType === 'text[]') { updatePatterns.push(`$${index}:name = $${index + 1}::text[]`); + values.push(fieldName, fieldValue); + index += 2; } else { - let type = 'text'; - for (const elt of fieldValue) { - if (typeof elt == 'object') { - type = 'json'; - break; + values.push(fieldName); + const buildSQLArray = fieldValue => { + let pattern = 'json_build_array('; + for (let i = 0; i < fieldValue.length; i += 1) { + const element = fieldValue[i]; + let type = ''; + if (Array.isArray(element)) { + pattern += buildSQLArray(element) + ','; + continue; + } else if (typeof element == 'object') { + type = '::json'; + } + values.push(element); + pattern += `$${index + 1}${type},`; + index += 1; } - if (typeof elt == 'number') { - type = 'numeric'; - break; + // remove last comma + if (fieldValue.length > 0) { + pattern = pattern.slice(0, -1); } - } - updatePatterns.push( - `$${index}:name = array_to_json($${index + 1}::${type}[])::jsonb` - ); + pattern += ')'; + return pattern; + }; + const sql = `$${index}:name = ${buildSQLArray(fieldValue)}`; + + updatePatterns.push(sql); + index += 1; } - values.push(fieldName, fieldValue); - index += 2; } else { debug('Not supported update', fieldName, fieldValue); return Promise.reject(