Skip to content

Commit 807372c

Browse files
authored
Fixing issue where running the evaluator multiple times with an expre… (#202)
* Fixing issue where running the evaluator multiple times with an expression with functions errored out. On the second run, the evaluator tried to use the same global context that was declared by the first one. The global context is now cleared after every evaluation. * Releasing 1.30
1 parent 94678b6 commit 807372c

File tree

5 files changed

+37
-12
lines changed

5 files changed

+37
-12
lines changed

docs/public/packages.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"packageId": "04tRb0000036fbRIAQ",
2+
"packageId": "04tRb0000036iJBIAY",
33
"componentPackageId": "04tRb0000012Mv8IAE"
44
}

expression-src/main/src/interpreter/Environment.cls

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,11 @@ public with sharing class Environment {
174174
public override Integer hashCode() {
175175
return (parentEnvironment != null ? parentEnvironment.hashCode() : 0) ^ (context != null ? context.hashCode() : 0) ^ variables.hashCode();
176176
}
177+
178+
public class ClearContext implements EvaluatorEventListener {
179+
public Map<String, Object> handle(EvaluatorEvent event) {
180+
GLOBAL_VARIABLES.clear();
181+
return null;
182+
}
183+
}
177184
}

expression-src/main/src/resolver/EvaluatorResolver.cls

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public with sharing abstract class EvaluatorResolver {
2525
public static EvaluatorResolver withoutContext() {
2626
return new BaseSingleRecordEvaluator(null);
2727
}
28-
28+
2929
/**
3030
* @description Analyzes multiple formulas and retrieves a record with all fields needed by those formulas
3131
* @param recordId The Id of the record to retrieve
@@ -36,14 +36,14 @@ public with sharing abstract class EvaluatorResolver {
3636
if (recordId == null || formulas == null || formulas.isEmpty()) {
3737
return null;
3838
}
39-
39+
4040
ContextResolver contextResolver = new ContextResolver(recordId, new List<Expr.FunctionDeclaration>());
41-
41+
4242
for (String formula : formulas) {
4343
try {
4444
List<Token> tokens = new Scanner(formula).scanTokens();
4545
List<Expr> expressions = new Parser(tokens).parse();
46-
46+
4747
for (Expr parsedExpression : expressions) {
4848
Expr desugaredExpression = new PipeResolver().resolve(parsedExpression);
4949
contextResolver.resolveForRecord(desugaredExpression);
@@ -53,26 +53,27 @@ public with sharing abstract class EvaluatorResolver {
5353
System.debug(LoggingLevel.WARN, 'Error analyzing formula "' + formula + '": ' + e.getMessage());
5454
}
5555
}
56-
56+
5757
if (!contextResolver.shouldExecuteQuery()) {
5858
return null;
5959
}
60-
60+
6161
// Add subqueries to the main query
6262
for (ContextResolver.Query subquery : contextResolver.getSubQueries()) {
6363
contextResolver.getQueryContext().queryBuilder.addSubquery(subquery.queryBuilder);
6464
}
65-
65+
6666
// Add condition to filter by the specific record id
6767
contextResolver.getQueryContext().queryBuilder.add(Q.condition('Id').isIn(new List<Id>{recordId}));
68-
68+
6969
// Execute the query and return the first record (if any)
7070
List<SObject> records = QDB.getInstance().run(contextResolver.getQueryContext().queryBuilder);
7171
return records.isEmpty() ? null : records[0];
7272
}
7373

7474
public EvaluationResult evaluate(String input, Configuration config) {
7575
config.subscribe(this.eventNotifier);
76+
eventNotifier.subscribe(OnEvaluationEndEvent.class, new Environment.ClearContext());
7677

7778
eventNotifier.notify(new OnEvaluationStartEvent(config));
7879

expression-src/spec/language/functions/FunctionDeclarationTest.cls

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,20 @@ private class FunctionDeclarationTest {
205205
Assert.areEqual(2, Limits.getQueries(), 'Two queries should have been consumed, ' +
206206
'since the function was called with the "nocache" keyword');
207207
}
208+
209+
@IsTest
210+
static void canRunEvaluatorMultipleTimesWhenUsingFunctions() {
211+
insert new Account(Name = 'ACME');
212+
213+
String expression = 'fun foo(n) => Query(Account(where: Name = n));\n' +
214+
'\n' +
215+
'[...foo("ACME"), ...foo("Salesforce")]';
216+
217+
try {
218+
Evaluator.run(expression);
219+
Evaluator.run(expression);
220+
} catch (Exception e) {
221+
Assert.fail('Should be able to run the evaluator multiple times: ' + e.getMessage());
222+
}
223+
}
208224
}

sfdx-project_packaging.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
{
44
"path": "expression-src",
55
"package": "Expression",
6-
"versionName": "Version 1.29",
7-
"versionNumber": "1.29.0.NEXT",
6+
"versionName": "Version 1.3",
7+
"versionNumber": "1.30.0.NEXT",
88
"default": false,
99
"versionDescription": "Expression core language",
1010
"ancestorVersion": "HIGHEST"
@@ -58,6 +58,7 @@
5858
"Expression@1.26.0-2": "04tRb0000034ahVIAQ",
5959
"Expression@1.27.0-2": "04tRb0000034eMvIAI",
6060
"Expression@1.28.0-2": "04tRb0000036OFdIAM",
61-
"Expression@1.29.0-2": "04tRb0000036fbRIAQ"
61+
"Expression@1.29.0-2": "04tRb0000036fbRIAQ",
62+
"Expression@1.30.0-2": "04tRb0000036iJBIAY"
6263
}
6364
}

0 commit comments

Comments
 (0)