Skip to content

Commit 5a978c0

Browse files
authored
toAggregatedMap with relationship (#213)
1 parent b474e71 commit 5a978c0

File tree

4 files changed

+80
-1
lines changed

4 files changed

+80
-1
lines changed

force-app/main/default/classes/main/soql-evaluator/SOQLEvaluator.cls

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public inherited sharing class SOQLEvaluator {
3737
Map<String, List<SObject>> toAggregatedMap(SObjectField keyField);
3838
Map<String, List<SObject>> toAggregatedMap(String relationshipName, SObjectField targetKeyField);
3939
Map<String, List<String>> toAggregatedMap(SObjectField keyField, SObjectField valueField);
40+
Map<String, List<String>> toAggregatedMap(SObjectField keyField, String relationshipName, SObjectField targetKeyField);
4041
}
4142

4243
public interface Mockable {
@@ -171,6 +172,10 @@ public inherited sharing class SOQLEvaluator {
171172
public Map<String, List<String>> toAggregatedMap(SObjectField keyField, SObjectField valueField) {
172173
return this.converter.transform(this.toList()).toAggregatedMap(keyField, valueField);
173174
}
175+
176+
public Map<String, List<String>> toAggregatedMap(SObjectField keyField, String relationshipName, SObjectField targetKeyField) {
177+
return this.converter.transform(this.toList()).toAggregatedMap(keyField, relationshipName, targetKeyField);
178+
}
174179
}
175180

176181
public class SoqlMock implements Mockable {

force-app/main/default/classes/main/soql-evaluator/SOQLEvaluator_Test.cls

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,42 @@ private class SOQLEvaluator_Test {
559559
Assert.areEqual(0, nameToDescriptions.size(), 'The size of the returned map should be 0.');
560560
}
561561

562+
@IsTest
563+
static void sObjectsToAggregatedMapWithKeyAndRelationshipValueFields() {
564+
// Setup
565+
insertAccountsWithParents();
566+
567+
// Test
568+
Map<String, List<String>> nameToDescriptions = SOQLEvaluator.of([SELECT Id, Name, Parent.Name FROM Account WHERE ParentId != NULL]).toAggregatedMap(Account.Name, 'Parent', Account.Name);
569+
570+
// Verify
571+
Assert.areEqual(2, nameToDescriptions.size(), 'The size of the returned map should be 2.');
572+
}
573+
574+
@IsTest
575+
static void sObjectsToAggregatedMapWithKeyAndRelationshipValueFieldsWithMocking() {
576+
// Setup
577+
SOQLEvaluator.mock('mockingQuery').thenReturn(new List<Account>{
578+
new Account(Name = 'Test 1', Parent = new Account(Name = 'Parent 1')),
579+
new Account(Name = 'Test 2', Parent = new Account(Name = 'Parent 2'))
580+
});
581+
582+
// Test
583+
Map<String, List<String>> parentNameToAccountNames = SOQLEvaluator.of([SELECT Id, Parent.Name FROM Account WHERE ParentId != NULL]).mockId('mockingQuery').toAggregatedMap(Account.Name, 'Parent', Account.Name);
584+
585+
// Verify
586+
Assert.areEqual(2, parentNameToAccountNames.size(), 'The size of the returned map should be 2.');
587+
}
588+
589+
@IsTest
590+
static void sObjectsToAggregatedMapWithKeyAndRelationshipValueFieldsWhenNoRecords() {
591+
// Test
592+
Map<String, List<String>> parentNameToAccountNames = SOQLEvaluator.of([SELECT Id, Parent.Name FROM Account WHERE ParentId != NULL]).toAggregatedMap(Account.Name, 'Parent', Account.Name);
593+
594+
// Verify
595+
Assert.areEqual(0, parentNameToAccountNames.size(), 'The size of the returned map should be 0.');
596+
}
597+
562598
@IsTest
563599
static void sObjectsMockStack() {
564600
// Setup

force-app/main/default/classes/main/standard-soql/SOQL.cls

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public virtual inherited sharing class SOQL implements Queryable {
156156
Id toId();
157157
Set<Id> toIds();
158158
Set<Id> toIdsOf(SObjectField field);
159-
Set<Id> toIdsOf(String relationshipName, SObjectField field);
159+
Set<Id> toIdsOf(String relationshipName, SObjectField targetKeyField);
160160
Boolean doExist();
161161
String toString();
162162
Object toValueOf(SObjectField fieldToExtract);
@@ -174,6 +174,7 @@ public virtual inherited sharing class SOQL implements Queryable {
174174
Map<String, List<SObject>> toAggregatedMap(SObjectField keyField);
175175
Map<String, List<SObject>> toAggregatedMap(String relationshipName, SObjectField targetKeyField);
176176
Map<String, List<String>> toAggregatedMap(SObjectField keyField, SObjectField valueField);
177+
Map<String, List<String>> toAggregatedMap(SObjectField keyField, String relationshipName, SObjectField targetKeyField);
177178
Database.QueryLocator toQueryLocator();
178179
}
179180

@@ -1037,6 +1038,13 @@ public virtual inherited sharing class SOQL implements Queryable {
10371038
return this.converter.transform(this.executor.toList()).toAggregatedMap(keyField, valueField);
10381039
}
10391040

1041+
public Map<String, List<String>> toAggregatedMap(SObjectField keyField, String relationshipName, SObjectField targetKeyField) {
1042+
this.builder.fields.clearAllFields(); // other fields not needed
1043+
this.with(keyField);
1044+
this.with(relationshipName + '.' + targetKeyField.toString());
1045+
return this.converter.transform(this.executor.toList()).toAggregatedMap(keyField, relationshipName, targetKeyField);
1046+
}
1047+
10401048
public Database.QueryLocator toQueryLocator() {
10411049
return this.executor.toQueryLocator();
10421050
}
@@ -2818,6 +2826,24 @@ public virtual inherited sharing class SOQL implements Queryable {
28182826
return customValuesPerCustomKey;
28192827
}
28202828

2829+
public Map<String, List<String>> toAggregatedMap(SObjectField keyField, String relationshipName, SObjectField targetKeyField) {
2830+
Map<String, List<String>> customValuesPerCustomKey = new Map<String, List<String>>();
2831+
List<String> relationshipPathFields = relationshipName.split('\\.');
2832+
2833+
for (SObject record : this.recordsToTransform) {
2834+
String key = String.valueOf(record.get(keyField));
2835+
String value = extractNestedFieldValue(record, relationshipPathFields, targetKeyField);
2836+
2837+
if (!customValuesPerCustomKey.containsKey(key)) {
2838+
customValuesPerCustomKey.put(key, new List<String>());
2839+
}
2840+
2841+
customValuesPerCustomKey.get(key).add(value);
2842+
}
2843+
2844+
return customValuesPerCustomKey;
2845+
}
2846+
28212847
private String extractNestedFieldValue(SObject parentRecord, List<String> relationshipPath, SObjectField targetField) {
28222848
SObject currentRecord = parentRecord;
28232849

force-app/main/default/classes/main/standard-soql/SOQL_Test.cls

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4507,6 +4507,18 @@ private class SOQL_Test {
45074507
Assert.isTrue(result.containsKey(null), 'The result map should have a null key for empty Industry.');
45084508
}
45094509

4510+
@IsTest
4511+
static void toAggregatedMapWithCustomKeyAndCustomRelationshipValue() {
4512+
// Setup
4513+
insertAccountsWithParents();
4514+
4515+
// Test
4516+
Map<String, List<String>> result = SOQL.of(Account.SObjectType).toAggregatedMap(Account.Name, 'Parent', Account.Id);
4517+
4518+
// Verify
4519+
Assert.areEqual(4, result.size(), 'The result map should have 4 keys for each account name.');
4520+
}
4521+
45104522
@IsTest
45114523
static void toQueryLocator() {
45124524
// Test

0 commit comments

Comments
 (0)