Skip to content

Commit

Permalink
Add semi-join feature
Browse files Browse the repository at this point in the history
Allow Query as the second parameter in the `lookup` and `addConditionIn`
methods, so that user can do semi-join queries.

For example, if user wants to do [ SELECT Id FROM Account WHERE Id IN
(SELECT AccountId FROM Opportunity) ], now he can do it in Query:

```
new Query('Account').lookup('AccountId',
        new Query('Opportunity').selectField('AccountId')).run();
```
  • Loading branch information
HenryRLee committed Nov 18, 2019
1 parent b52e995 commit 983d193
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/classes/Query.cls
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ public class Query {
return lookup(fieldName, new List<SObject>{sobj});
}

public Query lookup(String fieldName, Query query) {
return addConditionIn(fieldName, query);
}

/*
* Add a condition
* Example: addConditionEq('CreatedDate', Datetime.now())
Expand Down Expand Up @@ -323,6 +327,24 @@ public class Query {
return addCondition(conditionIn(lhs.getDescribe().getName(), rhs));
}

/*
* Add a semi-join condition
* Example: addConditionIn('Id', new Query('Opportunity').selectField('AccountId'))
* the condition is equivalent to "Id IN (SELECT AccountId FROM Opportunity)"
*/
public Query addConditionIn(String lhs, Query rhs) {
return addCondition(conditionIn(lhs, rhs));
}

/*
* Add a semi-join condition
* Example: addConditionIn(Account.Id, new Query('Opportunity').selectField('AccountId'))
* the condition is equivalent to "Id IN (SELECT AccountId FROM Opportunity)"
*/
public Query addConditionIn(Schema.SObjectField lhs, Query rhs) {
return addCondition(conditionIn(lhs.getDescribe().getName(), rhs));
}

/*
* Add a condition
* Example: addConditionNotIn('Name', mySet)
Expand Down Expand Up @@ -639,6 +661,32 @@ public class Query {
return conditionIn(lhs.getDescribe().getName(), rhs);
}

/*
* Create a semi-join condition
* Example: conditionIn('Id', new Query('Opportunity').selectField('AccountId'))
* the condition is equivalent to "Id IN (SELECT AccountId FROM Opportunity)"
*/
public static Condition conditionIn(String lhs, Query rhs) {
final String formatString = lhs + ' IN (' +
rhs.formQueryStringPreformat() + ')';

Condition condition = new Condition();

condition.conditionString = formatString;
condition.args = rhs.conditionArgs;

return condition;
}

/*
* Create a semi-join condition
* Example: conditionIn(Account.Id, new Query('Opportunity').selectField('AccountId'))
* the condition is equivalent to "Id IN (SELECT AccountId FROM Opportunity)"
*/
public static Condition conditionIn(Schema.SObjectField lhs, Query rhs) {
return conditionIn(lhs.getDescribe().getName(), rhs);
}

/*
* Create a condition
* Example: conditionNotIn('Name', mySet)
Expand Down
41 changes: 41 additions & 0 deletions src/classes/QueryTest.cls
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,47 @@ public class QueryTest {
System.assertEquals(resultMap.get('9'), null);
}

@isTest
static void semiJoinTest() {
Account acc = new Account(Name = 'New Account');
insert acc;

Opportunity opp = new Opportunity(
AccountId = acc.Id,
Name = 'New Opportunity',
CloseDate = Date.today().addDays(3),
TotalOpportunityQuantity = 10,
StageName = 'New',
IsPrivate = false);
insert opp;

Account acc2 = (Account)new Query('Account').
addConditionIn('Id', new Query('Opportunity').
selectField('AccountId').
byId(opp.Id)).
fetch();

System.assertEquals(acc.Id, acc2.Id);

Account acc3 = (Account)new Query('Account').
lookup('Id', new Query('Opportunity').
selectField('AccountId').
addConditionEq('StageName', 'New').
byId(opp.Id)).
addConditionEq('Name', 'New Account').
fetch();

System.assertEquals(acc.Id, acc3.Id);

Opportunity opp2 = (Opportunity)new Query('Opportunity').
lookup('AccountId', new Query('Account').
selectField('Id').
byId(acc.Id)).
fetch();

System.assertEquals(opp.Id, opp2.Id);
}

@isTest
static void debugTest() {
Id id = '001O000000qkv3KIAQ';
Expand Down

0 comments on commit 983d193

Please sign in to comment.