This was asked previously here however the answer isnt useful. Using an invocable class with a dynamic database query. If any of the fields in the query return a null value then the field is dropped from the response. That causes an error in the flow. Is there a way to ensure that the query returns ALL of the fields I requested? It's dynamic so one of the responses about initializing specific fields in the class is not useful.
For example for the dynamic query: SELECT Id, Field1__c, Field2__c from ACCOUNT
The Debug log shows this is what is queried.
If Field2__c = NULL then the class returns the following to the flow:
Id = '12345'
Field1__c = 'somevalue'
I need it to also return
Field2__c = null
This class is from UnofficialSF Execute SOQL
public static String replaceWithFormattedValues(String soqlQuery) {
String endingClause = '';
soqlQuery = soqlQuery.replaceAll('\r\n|\n|\r|\t',' ');
List<String> clausesToRemove = new List<String>{' order by ', ' limit ', ' group by ', ' offset ' };
for (String curClause : clausesToRemove) {
if (soqlQuery.containsIgnoreCase(curClause)) {
endingClause = curClause + soqlQuery.toLowerCase().substringAfter(curClause.toLowerCase());
soqlQuery = soqlQuery.removeEndIgnoreCase(endingClause);
break;
}
}
if (soqlQuery != null && soqlQuery.containsIgnoreCase(' from ') && soqlQuery.containsIgnoreCase('select ') && soqlQuery.containsIgnoreCase(' where ')) {
Pattern mPattern = pattern.compile('(?i)(?<=from )(.*)(?= where .+(\\(select .+\\)))');
Matcher mMatcher = mPattern.matcher(soqlQuery);
Boolean found = mMatcher.find();
String sObjectType = '';
if (found) {
sObjectType = mMatcher.group(0);
// Recurse through sub-queries
Pattern subPattern = pattern.compile('(?i)\\(select .+\\)');
Matcher subMatcher = subPattern.matcher(soqlQuery);
while (subMatcher.find()) {
String subQuery = subMatcher.group(0).removeStart('(').removeEnd(')');
String formattedSubQuery = replaceWithFormattedValues(subQuery);
soqlQuery = soqlQuery.replace(subQuery, formattedSubQuery);
}
} else {
mPattern = pattern.compile('(?i)(?<=from )(.*)(?= where)');
mMatcher = mPattern.matcher(soqlQuery);
if (mMatcher.find()) {
sObjectType = mMatcher.group(0);
System.debug('Logs: match found: sobject: ' + sObjectType);
} else {
throw new ExecuteSOQLException('Unable to parse query string: ' + soqlQuery);
}
}
Map<String, String> fieldNameValueMap = new Map<String, String>();
List<String> fieldNames = new List<String>();
mPattern = pattern.compile('(?i)(?<=where )(.*)');
mMatcher = mPattern.matcher(soqlQuery);
while (mMatcher.find()) {
String statement = mMatcher.group(0);
System.debug('Logs: match found: fields: ' + statement);
String whereClause = statement.replaceAll('(?i)\\(select .+\\)', '(SUBQUERY)');
fieldNames.addAll(whereClause.split('\\(|\\)|>=|<=|!=|=|>|<| in\\(| not in\\(| like | in:| or| and'));
}
if (!fieldNames.isEmpty()) {
for (Integer i = fieldNames.size() - 1; i >= 1; i -= 2) {
fieldNames[i - 1] = fieldNames[i - 1].replaceAll(' ', '');
fieldNameValueMap.put(fieldNames[i - 1], fieldNames.remove(i));
}
}
Map<String, String> fieldTypes = getFieldTypes(sObjectType, fieldNames);
soqlQuery = putFormattedValues(soqlQuery, fieldNameValueMap, fieldTypes);
}
return soqlQuery + endingClause
public static String putFormattedValues(String query, Map<String, String> fieldNameValueMap, Map<String, String> fieldTypes) {
Set<String> typesWithSpecialFormatting = new Set<String>{
'DATETIME', 'DATE'
};
for (String fieldName : fieldTypes.keySet()) {
if (typesWithSpecialFormatting.contains(fieldTypes.get(fieldName))) {
String formattedValue = getFormattedValue(fieldNameValueMap.get(fieldName), fieldTypes.get(fieldName));
query = query.replaceAll(fieldNameValueMap.get(fieldName).escapeJava(), formattedValue);
}
}
return query;
Database.query()definitely returns the null values. It appears that the Unofficial SF code is at fault, but the problem is likely inputFormattedValues(), which isn't shown here.