Believe it or not bind variables actually work in dynamic SOQL:
Map<Id,Account> accts = new Map<Id,Account>([select Id from Account]);
Set<Id> accountIds = accts.keySet();
String q = 'select id from Contact where AccountId in :accountIds';
List<Contact> cts = Database.query(q);
Note that you can't embed method calls (e.g. AccountId in :accts.keySet() would fail) when binding in this way.
This is a very, very good way of doing things as it offers a massive reduction in script statements, heap space, and even added security by automatically escaping input. I believe it also means that the bind data doesn't count against the 10k SOQL query character limit.
I can confirm there are a number of ISV apps that are dependent on this so there's no way salesforce could remove it in a future version without a massive outcry. This method is actually salesforce endorsed!
Also, see this question if you're having trouble with more complex uses, in short: you can only use an in-scope variable, not an actual expression with these binds.
JSON is a CPU hog; you may as well loop over your Set and cast each element individually at that point. You should not use JSON for converting a list to a set or vice versa. As an aside, you're also abusing a compiler bug by casting a List<String>
to a List<Id>
. You should be prepared for runtime exceptions if you do this. Realistically, you should fix the delegationDataMap to be Map<String, Set<Id>>
if it really is meant to be a set of Id values.
Best Answer
Here's a clever (ugly) one-liner.