diff --git a/lib/model/query/entities.js b/lib/model/query/entities.js index a62c21613..96c5109ef 100644 --- a/lib/model/query/entities.js +++ b/lib/model/query/entities.js @@ -34,10 +34,26 @@ const createSource = (details = null, subDefId = null, eventId = null) => ({ one //////////////////////////////////////////////////////////////////////////////// // ENTITY CREATE -const _defInsert = (id, root, creatorId, userAgent, label, json, version, dataReceived, sourceId = null, baseVersion = null, conflictingProperties = null) => sql` - insert into entity_defs ("entityId", "root", "sourceId", "creatorId", "userAgent", "label", "data", "current", "createdAt", "version", "baseVersion", "dataReceived", "conflictingProperties") - values (${id}, ${root}, ${sourceId}, ${creatorId}, ${userAgent}, ${label}, ${json}, true, clock_timestamp(), ${version}, ${baseVersion}, ${dataReceived}, ${conflictingProperties}) +const _defInsert = (id, root, creatorId, userAgent, partial, version, sourceId = null, baseVersion = null, conflictingProperties = null) => { + const json = JSON.stringify(partial.def.data); + const dataReceived = JSON.stringify(partial.def.dataReceived); + + return sql` + insert into entity_defs ("entityId", "createdAt", + "root", "current", + "sourceId", "creatorId", "userAgent", + "label", "data", "dataReceived", + "version", "baseVersion", + "conflictingProperties") + values (${id}, clock_timestamp(), + ${root}, true, + ${sourceId}, ${creatorId}, ${userAgent}, + ${partial.def.label}, ${json}, ${dataReceived}, + ${version}, ${baseVersion}, + ${conflictingProperties}) returning *`; +}; + const nextval = sql`nextval(pg_get_serial_sequence('entities', 'id'))`; // Creates both the entity and its initial entity def in one go. @@ -58,11 +74,8 @@ const createNew = (dataset, partial, subDef, sourceId, userAgentIn) => ({ one, c userAgent = blankStringToNull(userAgentIn); } - const json = JSON.stringify(partial.def.data); - const dataReceived = JSON.stringify(partial.def.dataReceived); - return one(sql` -with def as (${_defInsert(nextval, true, creatorId, userAgent, partial.def.label, json, 1, dataReceived, sourceId)}), +with def as (${_defInsert(nextval, true, creatorId, userAgent, partial, 1, sourceId)}), ins as (insert into entities (id, "datasetId", "uuid", "createdAt", "creatorId") select def."entityId", ${dataset.id}, ${partial.uuid}, def."createdAt", ${creatorId} from def returning entities.*) @@ -96,7 +109,6 @@ const createMany = (dataset, rawEntities, sourceId, userAgentIn) => async ({ all // Augment parsed entity data with dataset and creator IDs const entitiesForInsert = rawEntities.map(e => new Entity({ datasetId: dataset.id, creatorId, ...e })); - const entities = await all(sql`${insertMany(entitiesForInsert)} RETURNING id`); // Augment defs with IDs of freshly inserted entities and @@ -134,16 +146,12 @@ const createVersion = (dataset, partial, subDef, version, sourceId, baseVersion, userAgent = blankStringToNull(userAgentIn); } - const json = JSON.stringify(partial.def.data); - - const dataReceived = JSON.stringify(partial.def.dataReceived); - const conflictingPropJson = partial.def.conflictingProperties ? JSON.stringify(partial.def.conflictingProperties) : null; const _unjoiner = unjoiner(Entity, Entity.Def.into('currentVersion')); return one(sql` - with def as (${_defInsert(partial.id, false, creatorId, userAgent, partial.def.label, json, version, dataReceived, sourceId, baseVersion, conflictingPropJson)}), + with def as (${_defInsert(partial.id, false, creatorId, userAgent, partial, version, sourceId, baseVersion, conflictingPropJson)}), upd as (update entity_defs set current=false where entity_defs."entityId" = ${partial.id}), entities as (update entities set "updatedAt"=clock_timestamp(), conflict=${partial.conflict ?? sql`NULL`} where "uuid"=${partial.uuid} diff --git a/test/integration/api/entities.js b/test/integration/api/entities.js index df4c7df7b..3cef18d14 100644 --- a/test/integration/api/entities.js +++ b/test/integration/api/entities.js @@ -616,30 +616,33 @@ describe('Entities API', () => { }); })); - it('should get version source even when there is no corresponding create/update event', testEntities(async (service, container) => { + it('should get version source with source details even when there is no corresponding submission event', testEntities(async (service) => { const asAlice = await service.login('alice'); - await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc/versions') - .expect(200) - .then(({ body: versions }) => { - versions[0].should.have.property('source'); - versions[0].source.submission.instanceId.should.equal('one'); - versions[0].source.submission.should.have.property('currentVersion'); - versions[0].source.event.action.should.equal('submission.update'); + await asAlice.post('/v1/projects/1/datasets/people/entities') + .send({ + source: { + name: 'people.csv', + size: 100, + }, + entities: [ + { + uuid: '12345678-1234-4123-8234-111111111aaa', + label: 'Johnny Doe', + data: { + first_name: 'Johnny', + age: '22' + } + }, + ] }); - // this is simulating an entity version that doesnt have a corresponding create event - // e.g. made through bulk create (coming soon) - // but that can still look up source details directly from source table - await container.run(sql`delete from audits where action = 'entity.create'`); - - await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc/versions') + await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-111111111aaa/versions') .expect(200) .then(({ body: versions }) => { versions[0].should.have.property('source'); - versions[0].source.should.eql({ submission: { instanceId: 'one' } }); + versions[0].source.should.eql({ name: 'people.csv', size: 100, count: 1, userAgent: null }); }); - })); describe('relevantToConflict', () => {