Skip to content

Commit 07c4de6

Browse files
Merge pull request #53 from adangel/convert-currency
Support convertCurrency() function in SOQL and SOSL
2 parents 609d972 + bb50485 commit 07c4de6

File tree

6 files changed

+164
-3
lines changed

6 files changed

+164
-3
lines changed

antlr/ApexLexer.g4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ STANDARD : 'standard';
171171
DISTANCE : 'distance';
172172
GEOLOCATION : 'geolocation';
173173
GROUPING : 'grouping';
174+
CONVERT_CURRENCY : 'convertcurrency'; // used in both SOQL and SOSL
174175

175176
// SOQL Date functions
176177
CALENDAR_MONTH : 'calendar_month';

antlr/ApexParser.g4

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ soqlFunction
620620
| MAX LPAREN fieldName RPAREN
621621
| SUM LPAREN fieldName RPAREN
622622
| TOLABEL LPAREN fieldName RPAREN
623-
| FORMAT LPAREN fieldName RPAREN
623+
| FORMAT LPAREN ( fieldName | soqlFunction ) RPAREN
624624
| CALENDAR_MONTH LPAREN dateFieldName RPAREN
625625
| CALENDAR_QUARTER LPAREN dateFieldName RPAREN
626626
| CALENDAR_YEAR LPAREN dateFieldName RPAREN
@@ -637,6 +637,7 @@ soqlFunction
637637
| FIELDS LPAREN soqlFieldsParameter RPAREN
638638
| DISTANCE LPAREN locationValue COMMA locationValue COMMA StringLiteral RPAREN
639639
| GROUPING LPAREN fieldName RPAREN
640+
| CONVERT_CURRENCY LPAREN fieldName RPAREN
640641
;
641642

642643
dateFieldName
@@ -865,7 +866,9 @@ fieldSpec
865866

866867
fieldList
867868
: soslId (COMMA fieldList)*
868-
| TOLABEL LPAREN soslId RPAREN
869+
| TOLABEL LPAREN soslId RPAREN soslId?
870+
| CONVERT_CURRENCY LPAREN soslId RPAREN soslId?
871+
| FORMAT LPAREN (soslId | soqlFunction) RPAREN soslId?
869872
;
870873

871874
updateList
@@ -965,6 +968,7 @@ id
965968
| DISTANCE
966969
| GEOLOCATION
967970
| GROUPING
971+
| CONVERT_CURRENCY
968972
// SOQL date functions
969973
| CALENDAR_MONTH
970974
| CALENDAR_QUARTER
@@ -1164,6 +1168,7 @@ anyId
11641168
| DISTANCE
11651169
| GEOLOCATION
11661170
| GROUPING
1171+
| CONVERT_CURRENCY
11671172
// SOQL date functions
11681173
| CALENDAR_MONTH
11691174
| CALENDAR_QUARTER

jvm/src/test/java/io/github/apexdevtools/apexparser/SOQLParserTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,38 @@ void testGroupingFunction() {
130130
assertNotNull(context);
131131
assertEquals(0, parserAndCounter.getValue().getNumErrors());
132132
}
133+
134+
@Test
135+
void testConvertCurrency() {
136+
Map.Entry<ApexParser, SyntaxErrorCounter> parserAndCounter = createParser(
137+
"[ SELECT convertCurrency(Amount) FROM Opportunity ]"
138+
);
139+
ApexParser.SoqlLiteralContext context = parserAndCounter.getKey().soqlLiteral();
140+
assertNotNull(context);
141+
assertEquals(0, parserAndCounter.getValue().getNumErrors());
142+
}
143+
144+
@Test
145+
void testConvertCurrencyWithFormat() {
146+
Map.Entry<ApexParser, SyntaxErrorCounter> parserAndCounter = createParser(
147+
"[\n" +
148+
"SELECT Amount, FORMAT(amount) Amt, convertCurrency(amount) convertedAmount,\n" +
149+
" FORMAT(convertCurrency(amount)) convertedCurrency\n" +
150+
"FROM Opportunity where id = '006R00000024gDtIAI'\n" +
151+
"]"
152+
);
153+
ApexParser.SoqlLiteralContext context = parserAndCounter.getKey().soqlLiteral();
154+
assertNotNull(context);
155+
assertEquals(0, parserAndCounter.getValue().getNumErrors());
156+
}
157+
158+
@Test
159+
void testFormatWithAggregate() {
160+
Map.Entry<ApexParser, SyntaxErrorCounter> parserAndCounter = createParser(
161+
"[ SELECT FORMAT(MIN(closedate)) Amt FROM opportunity ]"
162+
);
163+
ApexParser.SoqlLiteralContext context = parserAndCounter.getKey().soqlLiteral();
164+
assertNotNull(context);
165+
assertEquals(0, parserAndCounter.getValue().getNumErrors());
166+
}
133167
}

jvm/src/test/java/io/github/apexdevtools/apexparser/SOSLParserTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,43 @@ void testToLabel() {
8484
assertNotNull(context);
8585
assertEquals(0, parserAndCounter.getValue().getNumErrors());
8686
}
87+
88+
@Test
89+
void testToLabelWithAlias() {
90+
Map.Entry<ApexParser, SyntaxErrorCounter> parserAndCounter = createParser(
91+
"[FIND :searchTerm IN ALL FIELDS RETURNING Account(Id, toLabel(Name) AliasName) LIMIT 10]");
92+
ApexParser.SoslLiteralContext context = parserAndCounter.getKey().soslLiteral();
93+
assertNotNull(context);
94+
assertEquals(0, parserAndCounter.getValue().getNumErrors());
95+
}
96+
97+
@Test
98+
void testConvertCurrency() {
99+
Map.Entry<ApexParser, SyntaxErrorCounter> parserAndCounter = createParser(
100+
"[ FIND 'test' RETURNING Opportunity(Name, convertCurrency(Amount), convertCurrency(Amount) AliasCurrency) ]"
101+
);
102+
ApexParser.SoslLiteralContext context = parserAndCounter.getKey().soslLiteral();
103+
assertNotNull(context);
104+
assertEquals(0, parserAndCounter.getValue().getNumErrors());
105+
}
106+
107+
@Test
108+
void testConvertCurrencyWithFormat() {
109+
Map.Entry<ApexParser, SyntaxErrorCounter> parserAndCounter = createParser(
110+
"[ FIND 'Acme' RETURNING Account(AnnualRevenue, FORMAT(convertCurrency(AnnualRevenue)) convertedCurrency) ]"
111+
);
112+
ApexParser.SoslLiteralContext context = parserAndCounter.getKey().soslLiteral();
113+
assertNotNull(context);
114+
assertEquals(0, parserAndCounter.getValue().getNumErrors());
115+
}
116+
117+
@Test
118+
void testFormatWithAggregate() {
119+
Map.Entry<ApexParser, SyntaxErrorCounter> parserAndCounter = createParser(
120+
"[ FIND 'Acme' RETURNING Account(AnnualRevenue, FORMAT(MIN(CloseDate))) ]"
121+
);
122+
ApexParser.SoslLiteralContext context = parserAndCounter.getKey().soslLiteral();
123+
assertNotNull(context);
124+
assertEquals(0, parserAndCounter.getValue().getNumErrors());
125+
}
87126
}

npm/src/__tests__/SOQLParserTest.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
3. The name of the author may not be used to endorse or promote products
1212
derived from this software without specific prior written permission.
1313
*/
14-
import { QueryContext, StatementContext } from "../ApexParser";
14+
import { QueryContext, StatementContext, SoqlLiteralContext } from "../ApexParser";
1515
import { createParser } from "./SyntaxErrorCounter";
1616

1717
test("SOQL Query", () => {
@@ -138,3 +138,37 @@ test("Grouping function", () => {
138138
expect(context).toBeInstanceOf(QueryContext);
139139
expect(errorCounter.getNumErrors()).toEqual(0);
140140
});
141+
142+
test("Convert Currency function", () => {
143+
const [parser, errorCounter] = createParser(
144+
'[ SELECT convertCurrency(Amount) FROM Opportunity ]'
145+
);
146+
const context = parser.soqlLiteral();
147+
148+
expect(context).toBeInstanceOf(SoqlLiteralContext);
149+
expect(errorCounter.getNumErrors()).toEqual(0);
150+
});
151+
152+
test("Convert Currency with format", () => {
153+
const [parser, errorCounter] = createParser(
154+
`[
155+
SELECT Amount, FORMAT(amount) Amt, convertCurrency(amount) convertedAmount,
156+
FORMAT(convertCurrency(amount)) convertedCurrency
157+
FROM Opportunity where id = '006R00000024gDtIAI'
158+
]`
159+
);
160+
const context = parser.soqlLiteral();
161+
162+
expect(context).toBeInstanceOf(SoqlLiteralContext);
163+
expect(errorCounter.getNumErrors()).toEqual(0);
164+
});
165+
166+
test("Format function with aggregate", () => {
167+
const [parser, errorCounter] = createParser(
168+
'[ SELECT FORMAT(MIN(closedate)) Amt FROM opportunity ]'
169+
)
170+
const context = parser.soqlLiteral();
171+
172+
expect(context).toBeInstanceOf(SoqlLiteralContext);
173+
expect(errorCounter.getNumErrors()).toEqual(0);
174+
});

npm/src/__tests__/SOSLParserTest.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,51 @@ test('testToLabel', () => {
8888
expect(context).toBeInstanceOf(SoslLiteralContext)
8989
expect(errorCounter.getNumErrors()).toEqual(0)
9090
})
91+
92+
test('testToLabelWithAlias', () => {
93+
const [parser, errorCounter] = createParser(
94+
"[FIND :searchTerm IN ALL FIELDS RETURNING Account(Id, toLabel(Name) AliasName) LIMIT 10]")
95+
const context = parser.soslLiteral()
96+
97+
expect(context).toBeInstanceOf(SoslLiteralContext)
98+
expect(errorCounter.getNumErrors()).toEqual(0)
99+
})
100+
101+
test('testConvertCurrency', () => {
102+
const [parser, errorCounter] = createParser(
103+
`[
104+
FIND 'test' RETURNING Opportunity(
105+
Name,
106+
convertCurrency(Amount),
107+
convertCurrency(Amount) AliasCurrency
108+
)
109+
]`)
110+
const context = parser.soslLiteral()
111+
112+
expect(context).toBeInstanceOf(SoslLiteralContext)
113+
expect(errorCounter.getNumErrors()).toEqual(0)
114+
})
115+
116+
test('testConvertCurrencyWithFormat', () => {
117+
const [parser, errorCounter] = createParser(
118+
`[
119+
FIND 'Acme' RETURNING Account(
120+
AnnualRevenue,
121+
FORMAT(convertCurrency(AnnualRevenue)) convertedCurrency
122+
)
123+
]`)
124+
const context = parser.soslLiteral()
125+
126+
expect(context).toBeInstanceOf(SoslLiteralContext)
127+
expect(errorCounter.getNumErrors()).toEqual(0)
128+
})
129+
130+
test('testFormatWithAggregate', () => {
131+
const [parser, errorCounter] = createParser(
132+
"[ FIND 'Acme' RETURNING Account(AnnualRevenue, FORMAT(MIN(CloseDate))) ]"
133+
)
134+
const context = parser.soslLiteral()
135+
136+
expect(context).toBeInstanceOf(SoslLiteralContext)
137+
expect(errorCounter.getNumErrors()).toEqual(0)
138+
})

0 commit comments

Comments
 (0)