From a0457fea0cc42fbc4f2e58a1f6d89683186ed6cc Mon Sep 17 00:00:00 2001 From: Austin Turner Date: Fri, 18 Jun 2021 18:18:07 -0600 Subject: [PATCH] fixed getFlattenedFields bug #157 `getFlattenedFields()` Did not return correct results if the aggregate function was nested in another function, such as `FORMAT(MAX(CreatedDate))` resolves #157 --- CHANGELOG.md | 7 ++ src/api/public-utils.ts | 3 +- src/utils.ts | 11 ++++ test/public-utils-test-data.ts | 113 +++++++++++++++++++++++++++++++++ test/public-utils.spec.ts | 2 +- 5 files changed, 134 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4391a1d..9ccd113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 4.2.1 + +June 18, 2021 + +#157 - `getFlattenedFields()` Did not return correct results if the aggregate function was nested in another function, such as `FORMAT(MAX(CreatedDate))`. +This bug only applied if there was not a field alias defined. + ## 4.2.0 June 8, 2021 diff --git a/src/api/public-utils.ts b/src/api/public-utils.ts index db21e8d..82fa4b1 100644 --- a/src/api/public-utils.ts +++ b/src/api/public-utils.ts @@ -11,6 +11,7 @@ import { isGroupByFn, isHavingClauseWithRightCondition, isNegationCondition, + isNestedParamAggregateFunction, isOrderByField, isOrderByFn, isString, @@ -209,7 +210,7 @@ export function getFlattenedFields( return field.alias; } // Non-aliased aggregate fields use computed name expr0, expr1, etc.. - if (field.isAggregateFn || isAggregateResult) { + if (field.isAggregateFn || isNestedParamAggregateFunction(field) || isAggregateResult) { currUnAliasedAggExp++; return `expr${currUnAliasedAggExp}`; } diff --git a/src/utils.ts b/src/utils.ts index 61a043b..24f2249 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -115,6 +115,17 @@ export function getParams(functionFieldExp: FieldFunctionExpression): string[] { return getParams(functionFieldExp.parameters[0] as FieldFunctionExpression); } +export function isNestedParamAggregateFunction(functionFieldExp: FieldFunctionExpression): boolean { + if (!functionFieldExp.parameters || functionFieldExp.parameters.length === 0) { + return false; + } + const parameter = functionFieldExp.parameters[0]; + if (isString(parameter)) { + return false; + } + return !!parameter.isAggregateFn; +} + export function hasAlias(value: any): value is FieldWithAlias | FieldRelationshipWithAlias { return value && !isNil(value.alias); } diff --git a/test/public-utils-test-data.ts b/test/public-utils-test-data.ts index 975481a..1e9719d 100644 --- a/test/public-utils-test-data.ts +++ b/test/public-utils-test-data.ts @@ -446,4 +446,117 @@ export const testCases: FlattenedObjTestCase[] = [ AcctCreatedDate: '2020-02-28T03:00:31.000+0000', }, }, + { + testCase: 14, + expectedFields: ['expr0', 'myDate', 'Email'], + query: { + fields: [ + { + type: 'FieldFunctionExpression', + functionName: 'COUNT', + parameters: ['Id'], + isAggregateFn: true, + rawValue: 'COUNT(Id)', + }, + { + type: 'FieldFunctionExpression', + functionName: 'FORMAT', + alias: 'myDate', + parameters: [ + { + type: 'FieldFunctionExpression', + functionName: 'MAX', + parameters: ['CreatedDate'], + isAggregateFn: true, + rawValue: 'MAX(CreatedDate)', + }, + ], + rawValue: 'FORMAT(MAX(CreatedDate))', + }, + { + type: 'Field', + field: 'Email', + }, + ], + sObject: 'Contact', + groupBy: [ + { + field: 'Email', + }, + ], + having: { + left: { + fn: { + functionName: 'COUNT', + parameters: ['Id'], + rawValue: 'COUNT(Id)', + }, + operator: '>=', + value: '0', + literalType: 'INTEGER', + }, + }, + }, + sfdcObj: { + expr0: 16, + myDate: '7/13/2018 7:07 AM', + Email: 'agreen@foo.com', + }, + }, + { + testCase: 15, + expectedFields: ['expr0', 'expr1', 'Email'], + query: { + fields: [ + { + type: 'FieldFunctionExpression', + functionName: 'COUNT', + parameters: ['Id'], + isAggregateFn: true, + rawValue: 'COUNT(Id)', + }, + { + type: 'FieldFunctionExpression', + functionName: 'FORMAT', + parameters: [ + { + type: 'FieldFunctionExpression', + functionName: 'MAX', + parameters: ['CreatedDate'], + isAggregateFn: true, + rawValue: 'MAX(CreatedDate)', + }, + ], + rawValue: 'FORMAT(MAX(CreatedDate))', + }, + { + type: 'Field', + field: 'Email', + }, + ], + sObject: 'Contact', + groupBy: [ + { + field: 'Email', + }, + ], + having: { + left: { + fn: { + functionName: 'COUNT', + parameters: ['Id'], + rawValue: 'COUNT(Id)', + }, + operator: '>=', + value: '0', + literalType: 'INTEGER', + }, + }, + }, + sfdcObj: { + expr0: 16, + expr1: '7/13/2018 7:07 AM', + Email: 'agreen@foo.com', + }, + }, ]; diff --git a/test/public-utils.spec.ts b/test/public-utils.spec.ts index 393890c..e179c81 100644 --- a/test/public-utils.spec.ts +++ b/test/public-utils.spec.ts @@ -211,7 +211,7 @@ describe('getFlattenedFields', () => { const fields = utils.getFlattenedFields(testCase.query); expect(fields).to.deep.equal(testCase.expectedFields); fields.forEach(field => { - expect(lodashGet(testCase.sfdcObj, field)).to.not.be.undefined; + expect(lodashGet(testCase.sfdcObj, field), `${field} does not exist on sfdc record`).to.not.be.undefined; }); }); });