Skip to content

Commit 75e8fb4

Browse files
committed
Merge pull request apex-enterprise-patterns#76 from capeterson/develop
Rollup FF internal updates to QueryFactory
2 parents bdc7def + 34900ff commit 75e8fb4

File tree

4 files changed

+465
-35
lines changed

4 files changed

+465
-35
lines changed

fflib/src/classes/fflib_QueryFactory.cls

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
**/
2626

2727
/**
28-
* QueryFactor provides an object-oriented way of building SOQL queries without resorting to string manipulation.
28+
* QueryFactory provides an object-oriented way of building SOQL queries without resorting to string manipulation.
2929
* This class is not meant to be used as a replacement for all SOQL queries, and due to the relativley high overhead in both CPU and describe calls
3030
* should be used in places where highly dynamic queries, such as those that include field sets or are mutated heavilly
3131
* in multiple locations are a good fit for use with fflib_QueryFactory.
@@ -36,10 +36,10 @@
3636
* Currently the WHERE clause of the query is manipulated as a single string, and is decidedly less OO-styled than other methods.
3737
* This is expected to be expanded upon in the future.
3838
*
39-
* To include one or more sort expression(s), use one of the addOrdering methods. If not specified, the "NULLS FIRST" keywords
40-
* will be included by default.
39+
* To include one or more ORDER BY clause(s), use one of the addOrdering methods. If not specified, the "NULLS FIRST" keywords
40+
* will be included by default. Constructing Ordering instances manually is discouraged.
4141
*
42-
* Subselect Queries are supported with the subselectQuery method.
42+
* Subselect Queries are supported with the subselectQuery methods.
4343
* More than one sub-query can be added to a single query, but sub-queries can only be 1 level deep.
4444
* An exception will thrown from the subselectQuery method when there is an attempt to add a subquery to a sub-query
4545
* or to add a subquery to a query with an invalid relationship.
@@ -66,11 +66,6 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
6666
private Integer limitCount;
6767
private Integer offset;
6868
private List<Ordering> order;
69-
/**
70-
* each item in sortExpressions contains the field and the direction (ascending or descending)
71-
* use the addOrdering method to add fields to sort by. the sort fields
72-
* appear in the SOQL query in the order they are added to the query.
73-
**/
7469
/**
7570
/* Integrate checking for READ Field Level Security within the selectField(s) methods
7671
/* This can optionally be enforced (or not) by calling the setEnforceFLS method prior to calling
@@ -327,24 +322,74 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
327322
/**
328323
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
329324
* If not, a new one will be created and returned.
325+
* @deprecated Replaced by {@link #subselectQuery(String relationshipName)} and {@link #subselectQuery(ChildRelationship relationship)}
330326
* @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
331327
* @param related The related object type
332328
**/
333329
public fflib_QueryFactory subselectQuery(SObjectType related){
330+
System.debug(LoggingLevel.WARN, 'fflib_QueryFactory.subselectQuery(Schema.SObjectType) is deprecated and will be removed in a future release. Use fflib_QueryFactory.subselectQuery(String) or fflib_QueryFactory.subselectQuery(ChildRelationship) instead.');
334331
return setSubselectQuery(getChildRelationship(related), false);
335332
}
336333

337334
/**
338335
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
339336
* If not, a new one will be created and returned.
337+
* @deprecated Replaced by {@link #subselectQuery(String relationshipName, Boolean assertIsAccessible)} and {@link #subselectQuery(ChildRelationship relationship, Boolean assertIsAccessible)}
340338
* @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
341339
* @param related The related object type
342340
* @param assertIsAccessible indicates whether to check if the user has access to the subquery object
343341
**/
344-
public fflib_QueryFactory subselectQuery(SObjectType related, Boolean assertIsAccessible){
342+
public fflib_QueryFactory subselectQuery(SObjectType related, Boolean assertIsAccessible){
343+
System.debug(LoggingLevel.WARN, 'fflib_QueryFactory.subselectQuery(Schema.SObjectType, Boolean) is deprecated and will be removed in a future release. Use fflib_QueryFactory.subselectQuery(String, Boolean) or fflib_QueryFactory.subselectQuery(ChildRelationship, Boolean) instead.');
345344
return setSubselectQuery(getChildRelationship(related), assertIsAccessible);
346345
}
347346

347+
/**
348+
* Add a subquery query to this query. If a subquery for this relationshipName already exists, it will be returned.
349+
* If not, a new one will be created and returned.
350+
* @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
351+
* @param relationshipName The relationshipName to be added as a subquery
352+
**/
353+
public fflib_QueryFactory subselectQuery(String relationshipName){
354+
return subselectQuery(relationshipName, false);
355+
}
356+
357+
/**
358+
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
359+
* If not, a new one will be created and returned.
360+
* @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
361+
* @param relationshipName The relationshipName to be added as a subquery
362+
* @param assertIsAccessible indicates whether to check if the user has access to the subquery object
363+
**/
364+
public fflib_QueryFactory subselectQuery(String relationshipName, Boolean assertIsAccessible){
365+
ChildRelationship relationship = getChildRelationship(relationshipName);
366+
if (relationship != null) {
367+
return setSubselectQuery(relationship, assertIsAccessible);
368+
}
369+
throw new InvalidSubqueryRelationshipException('Invalid call to subselectQuery with relationshipName = '+relationshipName +'. Relationship does not exist for ' + table.getDescribe().getName());
370+
}
371+
372+
/**
373+
* Add a subquery query to this query. If a subquery for this relationshipName already exists, it will be returned.
374+
* If not, a new one will be created and returned.
375+
* @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
376+
* @param relationship The ChildRelationship to be added as a subquery
377+
**/
378+
public fflib_QueryFactory subselectQuery(ChildRelationship relationship){
379+
return subselectQuery(relationship, false);
380+
}
381+
382+
/**
383+
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
384+
* If not, a new one will be created and returned.
385+
* @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
386+
* @param relationship The ChildRelationship to be added as a subquery
387+
* @param assertIsAccessible indicates whether to check if the user has access to the subquery object
388+
**/
389+
public fflib_QueryFactory subselectQuery(ChildRelationship relationship, Boolean assertIsAccessible){
390+
return setSubselectQuery(relationship, assertIsAccessible);
391+
}
392+
348393
/**
349394
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
350395
* If not, a new one will be created and returned.
@@ -393,6 +438,19 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
393438
throw new InvalidSubqueryRelationshipException('Invalid call to subselectQuery. Invalid relationship for table '+table + ' and objtype='+objType);
394439
}
395440

441+
/**
442+
* Get the ChildRelationship from the Table for the relationship name passed in.
443+
* @param relationshipName The name of the object's ChildRelationship on get
444+
**/
445+
private Schema.ChildRelationship getChildRelationship(String relationshipName){
446+
for (Schema.ChildRelationship childRow : table.getDescribe().getChildRelationships()){
447+
if (childRow.getRelationshipName() == relationshipName){
448+
return childRow;
449+
}
450+
}
451+
return null;
452+
}
453+
396454
/**
397455
* Add a field to be sorted on. This may be a direct field or a field
398456
* related through an object lookup or master-detail relationship.
@@ -504,6 +562,33 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
504562
result += ' LIMIT '+limitCount;
505563
return result;
506564
}
565+
566+
/**
567+
* Create a "deep" clone of this object that can be safely mutated without affecting the cloned instance
568+
* @return a deep clone of this fflib_QueryFactory
569+
**/
570+
public fflib_QueryFactory deepClone(){
571+
572+
fflib_QueryFactory clone = new fflib_QueryFactory(this.table)
573+
.setLimit(this.limitCount)
574+
.setCondition(this.conditionExpression)
575+
.setEnforceFLS(this.enforceFLS);
576+
577+
Map<Schema.ChildRelationship, fflib_QueryFactory> subqueries = this.subselectQueryMap;
578+
if(subqueries != null) {
579+
Map<Schema.ChildRelationship, fflib_QueryFactory> clonedSubqueries = new Map<Schema.ChildRelationship, fflib_QueryFactory>();
580+
for(Schema.ChildRelationship key : subqueries.keySet()) {
581+
clonedSubqueries.put(key, subqueries.get(key).deepClone());
582+
}
583+
clone.subselectQueryMap = clonedSubqueries;
584+
}
585+
586+
clone.relationship = this.relationship;
587+
clone.order = this.order.clone();
588+
clone.fields = this.fields.clone();
589+
590+
return clone;
591+
}
507592

508593
public class Ordering{
509594
private SortOrder direction;

0 commit comments

Comments
 (0)