diff --git a/lib/make/makeAggregatePipeline.js b/lib/make/makeAggregatePipeline.js index 10048622..967aa793 100644 --- a/lib/make/makeAggregatePipeline.js +++ b/lib/make/makeAggregatePipeline.js @@ -598,6 +598,14 @@ function makeAggregatePipeline(ast, context = {}) { pipeline, (p) => !!p.$project ); + const replaceRootAfterPreviousProject = pipeline.findIndex( + (step, index) => { + if (index < previousProjectIndex) { + return false; + } + return !!step.$replaceRoot; + } + ); // previous project stage found if (previousProjectIndex > -1) { @@ -669,13 +677,24 @@ function makeAggregatePipeline(ast, context = {}) { for (const key of unsetKeys) { projectObj[key] = 1; } + let replaceRoot = null; + if ( + replaceRootAfterPreviousProject > previousProjectIndex + ) { + replaceRoot = pipeline[replaceRootAfterPreviousProject]; + pipeline.splice(replaceRootAfterPreviousProject, 1); + } pipeline.splice(previousProjectIndex, 1); pipeline.push({$project: projectObj}); pipeline.push({$sort: sortObj}); pipeline.push({$unset: unsetKeys}); + if (removePrefixes.length > 0) { pipeline.push({$unset: removePrefixes}); } + if (replaceRoot) { + pipeline.push(replaceRoot); + } } else { pipeline.push({$sort: sortObj}); } diff --git a/package.json b/package.json index 065c1282..1ddabe45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@synatic/noql", - "version": "4.2.4", + "version": "4.2.5", "description": "Convert SQL statements to mongo queries or aggregates", "main": "index.js", "files": [ diff --git a/test/bug-fix-tests/bug-fix.json b/test/bug-fix-tests/bug-fix.json index 04767ceb..55988d18 100644 --- a/test/bug-fix-tests/bug-fix.json +++ b/test/bug-fix-tests/bug-fix.json @@ -1308,5 +1308,30 @@ }, "sort-after-project": { "case-1": {} + }, + "invalid-sort-order": { + "case-1": { + "expectedResults": [ + { + "RecordId": "recordId", + "AncestorInstanceId": null, + "AncestorRecordId": null, + "AncestorRecordNumber": null, + "ChecklistStatusId": "ChecklistStatusId", + "CurrentDv": "2021-08-28T06:57:40.097Z", + "InsertDv": "2021-08-28T06:54:50.200Z", + "InstanceId": "InstanceId", + "IsInUseByOtherRecords": 0, + "ModuleId": "ModuleId", + "ProcessFlowId": "ProcessFlowId", + "RecordNumber": 1, + "RecordStatus": "active", + "SQ": 12345, + "CreatedByUserId": "admin", + "LatestModifiedByUserId": "admin", + "DeletedByUserId": null + } + ] + } } } \ No newline at end of file diff --git a/test/bug-fix-tests/bug-fix.test.js b/test/bug-fix-tests/bug-fix.test.js index 222879f8..dec157f1 100644 --- a/test/bug-fix-tests/bug-fix.test.js +++ b/test/bug-fix-tests/bug-fix.test.js @@ -83,7 +83,7 @@ describe('bug-fixes', function () { // const res = await queryResultTester({ // queryString: queryString, // casePath: 'bugfix.current-date.case2', - // mode: 'write', + // mode, // }); // const correctHcp = [ // { @@ -387,7 +387,7 @@ describe('bug-fixes', function () { await queryResultTester({ queryString: queryString, casePath: 'bugfix.ntile.case1', - mode: 'write', + mode, outputPipeline: true, }); }); @@ -1159,7 +1159,7 @@ describe('bug-fixes', function () { await queryResultTester({ queryString: queryString, casePath: 'deeply-nested-divide.case1', - mode: 'write', + mode, outputPipeline: false, }); }); @@ -1189,7 +1189,7 @@ describe('bug-fixes', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'and-or-nor.case-1', - mode: 'write', + mode, outputPipeline: false, skipDbQuery: true, optimizeJoins: true, @@ -2117,7 +2117,7 @@ describe('bug-fixes', function () { await queryResultTester({ queryString: queryString, casePath: 'nin.case-2', - mode: 'write', + mode, outputPipeline: true, skipDbQuery: true, optimizeJoins: false, @@ -2199,7 +2199,7 @@ describe('bug-fixes', function () { await queryResultTester({ queryString: queryString, casePath: 'nested-case.case-1', - mode: 'write', + mode, outputPipeline: false, skipDbQuery: true, optimizeJoins: false, @@ -2257,7 +2257,7 @@ describe('bug-fixes', function () { await queryResultTester({ queryString: queryString, casePath: 'nested-case.case-2', - mode: 'write', + mode, outputPipeline: false, skipDbQuery: false, optimizeJoins: false, @@ -3077,181 +3077,22 @@ from (select RecordId, CreatedByUserId, LatestModifiedByUserId, DeletedByUserId - from \`global-list-module-records--vbfr-std-glb-module-record\` + from \`global-list-module-records-vbfr-std-glb-module-record\` where RecordStatus in ('active') - and InstanceId in ('19F881AA-94BA-4F9A-8E04-C37B172AF652' ) + and InstanceId in ('InstanceId' ) ) as records where 1=1 order by CurrentDv asc , SQ asc`; await queryResultTester({ queryString: sql, - casePath: 'nested-case.case-2', - mode: 'write', + casePath: 'invalid-sort-order.case-1', + mode, outputPipeline: false, - skipDbQuery: true, + expectZeroResults: false, + skipDbQuery: false, optimizeJoins: false, unsetId: true, - schemas: { - // 'global-list-module-records--vbfr-std-glb-module-record': { - // type: 'object', - // properties: { - // _id: { - // type: 'string', - // format: 'mongoid', - // }, - // RecordId: { - // type: 'string', - // stringLength: 36, - // }, - // AncestorInstanceId: { - // type: 'null', - // }, - // AncestorRecordId: { - // type: 'null', - // }, - // AncestorRecordNumber: { - // type: 'null', - // }, - // AuditSQ: { - // type: 'null', - // }, - // ChecklistStatusId: { - // type: ['null', 'string'], - // stringLength: 36, - // }, - // CreatedByUserId: { - // type: 'string', - // stringLength: 36, - // }, - // CurrentDv: { - // type: 'string', - // format: 'date-time', - // }, - // DeletedByUserId: { - // type: 'null', - // }, - // InsertDv: { - // type: 'string', - // format: 'date-time', - // }, - // InstanceId: { - // type: 'string', - // stringLength: 36, - // }, - // IsInUseByOtherRecords: { - // type: 'integer', - // }, - // LatestModifiedByUserId: { - // type: 'string', - // stringLength: 36, - // }, - // ModuleId: { - // type: 'string', - // stringLength: 36, - // }, - // ProcessFlowId: { - // type: 'string', - // stringLength: 36, - // }, - // RecordNumber: { - // type: 'integer', - // }, - // RecordStatus: { - // type: 'string', - // stringLength: 6, - // }, - // SQ: { - // type: 'integer', - // }, - // _dateUpdated: { - // type: 'string', - // format: 'date-time', - // }, - // }, - // }, - }, }); - const aggr = makeMongoAggregate(sql); - assert.deepStrictEqual( - aggr, - { - pipeline: [ - { - $match: { - $and: [ - { - RecordStatus: { - $in: ['active'], - }, - }, - { - InstanceId: { - $in: [ - '19F881AA-94BA-4F9A-8E04-C37B172AF652', - ], - }, - }, - ], - }, - }, - { - $project: { - RecordId: '$RecordId', - AncestorInstanceId: '$AncestorInstanceId', - AncestorRecordId: '$AncestorRecordId', - AncestorRecordNumber: '$AncestorRecordNumber', - ChecklistStatusId: '$ChecklistStatusId', - CurrentDv: '$CurrentDv', - InsertDv: '$InsertDv', - InstanceId: '$InstanceId', - IsInUseByOtherRecords: '$IsInUseByOtherRecords', - ModuleId: '$ModuleId', - ProcessFlowId: '$ProcessFlowId', - RecordNumber: '$RecordNumber', - RecordStatus: '$RecordStatus', - SQ: '$SQ', - CreatedByUserId: '$CreatedByUserId', - LatestModifiedByUserId: - '$LatestModifiedByUserId', - DeletedByUserId: '$DeletedByUserId', - }, - }, - { - $match: { - $expr: { - $eq: [1, 1], - }, - }, - }, - { - $replaceRoot: { - newRoot: '$records', - }, - }, - { - $project: { - records: '$$ROOT', - CurrentDv: 1, - SQ: 1, - }, - }, - { - $sort: { - CurrentDv: 1, - SQ: 1, - }, - }, - { - $unset: ['CurrentDv', 'SQ'], - }, - ], - collections: [ - 'global-list-module-records--vbfr-std-glb-module-record', - ], - type: 'aggregate', - }, - 'Invalid sort order' - ); }); }); }); diff --git a/test/exampleData/global-list-module-records-vbfr-std-glb-module-record.json b/test/exampleData/global-list-module-records-vbfr-std-glb-module-record.json new file mode 100644 index 00000000..02a52acf --- /dev/null +++ b/test/exampleData/global-list-module-records-vbfr-std-glb-module-record.json @@ -0,0 +1,21 @@ +[ + { + "RecordId": "recordId", + "AncestorInstanceId": null, + "AncestorRecordId": null, + "AncestorRecordNumber": null, + "ChecklistStatusId": "ChecklistStatusId", + "CurrentDv": "2021-08-28T06:57:40.097Z", + "InsertDv": "2021-08-28T06:54:50.200Z", + "InstanceId": "InstanceId", + "IsInUseByOtherRecords": 0, + "ModuleId": "ModuleId", + "ProcessFlowId": "ProcessFlowId", + "RecordNumber": 1, + "RecordStatus": "active", + "SQ": 12345, + "CreatedByUserId": "admin", + "LatestModifiedByUserId": "admin", + "DeletedByUserId": null + } +] diff --git a/test/joins/joins.test.js b/test/joins/joins.test.js index d8631206..9f6d46f8 100644 --- a/test/joins/joins.test.js +++ b/test/joins/joins.test.js @@ -207,7 +207,7 @@ describe('joins', function () { const {pipeline, results} = await queryResultTester({ queryString, casePath: 'left-join.no-alias.case-1', - mode: 'write', + mode, skipDbQuery: false, }); const lookup = pipeline.find((p) => !!p.$lookup); @@ -695,7 +695,7 @@ describe('joins', function () { const {pipeline} = await queryResultTester({ queryString, casePath: 'optimize.explicit', - mode: 'write', + mode, unsetId: false, }); @@ -708,7 +708,7 @@ describe('joins', function () { const {pipeline} = await queryResultTester({ queryString, casePath: 'optimize.explicit', - mode: 'write', + mode, }); assert.deepStrictEqual(pipeline, expectedPipeline); diff --git a/test/optimizations/optimizations.test.js b/test/optimizations/optimizations.test.js index 6e8f8c60..120f89ed 100644 --- a/test/optimizations/optimizations.test.js +++ b/test/optimizations/optimizations.test.js @@ -2433,7 +2433,7 @@ describe('optimizations', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'where.case-31', - mode: 'write', + mode, outputPipeline, optimizeJoins: true, unsetId: false, @@ -2792,7 +2792,7 @@ describe('optimizations', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'where.case-35', - mode: 'write', + mode, outputPipeline, optimizeJoins: true, unsetId: false, @@ -2978,7 +2978,7 @@ describe('optimizations', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'where.case-37', - mode: 'write', + mode, outputPipeline, optimizeJoins: true, unsetId: false, @@ -3236,7 +3236,7 @@ describe('optimizations', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'where.case-40', - mode: 'write', + mode, outputPipeline, optimizeJoins: true, unsetId: false, @@ -3421,7 +3421,7 @@ describe('optimizations', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'use-cases.case-1', - mode: 'write', + mode, outputPipeline, skipDbQuery: true, optimizeJoins: true, @@ -3543,7 +3543,7 @@ describe('optimizations', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'use-cases.case-2', - mode: 'write', + mode, outputPipeline, skipDbQuery: true, optimizeJoins: true, @@ -3873,7 +3873,7 @@ describe('optimizations', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'use-cases.case-2', - mode: 'write', + mode, outputPipeline, skipDbQuery: true, optimizeJoins: true, @@ -4441,7 +4441,7 @@ describe('optimizations', function () { const {pipeline} = await queryResultTester({ queryString: queryString, casePath: 'use-cases.case-2', - mode: 'write', + mode, outputPipeline, skipDbQuery: true, optimizeJoins: true,