Skip to content

Commit d7208b7

Browse files
committed
Fix
1 parent be99181 commit d7208b7

File tree

1 file changed

+119
-47
lines changed

1 file changed

+119
-47
lines changed

website/src/pages/playground.js

Lines changed: 119 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import Layout from '@theme/Layout';
33
import Heading from '@theme/Heading';
44

@@ -22,6 +22,9 @@ class SOQLToSOQLLibTranslator {
2222
this.reset();
2323
const cleanQuery = soqlQuery.trim().replace(/\s+/g, ' ');
2424

25+
// Check if query explicitly specifies SYSTEM_MODE
26+
const hasSystemMode = /WITH\s+SYSTEM_MODE/i.test(cleanQuery);
27+
2528
// Extract SObject from FROM clause
2629
this.parseSObjectType(cleanQuery);
2730

@@ -49,7 +52,7 @@ class SOQLToSOQLLibTranslator {
4952
// Parse FOR clause
5053
this.parseForClause(cleanQuery);
5154

52-
return this.generateSOQLLibCode();
55+
return this.generateSOQLLibCode(hasSystemMode);
5356
} catch (error) {
5457
return `// Error parsing SOQL: ${error.message}\n// Please check your SOQL syntax and try again.`;
5558
}
@@ -378,7 +381,7 @@ class SOQLToSOQLLibTranslator {
378381
}
379382

380383
parseWhereClause(query) {
381-
const whereMatch = query.match(/WHERE\s+(.*?)(?:\s+(?:GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|FOR\s+(?:UPDATE|VIEW|REFERENCE)|ALL\s+ROWS)\s|$)/i);
384+
const whereMatch = query.match(/WHERE\s+(.*?)(?:\s+(?:GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|FOR\s+(?:UPDATE|VIEW|REFERENCE)|ALL\s+ROWS|WITH\s+(?:USER_MODE|SYSTEM_MODE))|\s*$)/i);
382385
if (whereMatch) {
383386
const whereClause = whereMatch[1].trim();
384387
this.whereConditions = this.parseConditions(whereClause);
@@ -633,23 +636,23 @@ class SOQLToSOQLLibTranslator {
633636
}
634637

635638
parseOrderByClause(query) {
636-
const orderByMatch = query.match(/ORDER\s+BY\s+(.*?)(?:\s+(?:LIMIT|OFFSET|FOR\s+(?:UPDATE|VIEW|REFERENCE)|ALL\s+ROWS)\s|$)/i);
639+
const orderByMatch = query.match(/ORDER\s+BY\s+(.*?)(?:\s+(?:LIMIT|OFFSET|FOR\s+(?:UPDATE|VIEW|REFERENCE)|ALL\s+ROWS|WITH\s+(?:USER_MODE|SYSTEM_MODE))|\s*$)/i);
637640
if (orderByMatch) {
638641
const orderByClause = orderByMatch[1].trim();
639642
this.orderByFields = orderByClause.split(',').map(field => field.trim());
640643
}
641644
}
642645

643646
parseGroupByClause(query) {
644-
const groupByMatch = query.match(/GROUP\s+BY\s+(.*?)(?:\s+(?:HAVING|ORDER\s+BY|LIMIT|OFFSET|FOR\s+(?:UPDATE|VIEW|REFERENCE)|ALL\s+ROWS)\s|$)/i);
647+
const groupByMatch = query.match(/GROUP\s+BY\s+(.*?)(?:\s+(?:HAVING|ORDER\s+BY|LIMIT|OFFSET|FOR\s+(?:UPDATE|VIEW|REFERENCE)|ALL\s+ROWS|WITH\s+(?:USER_MODE|SYSTEM_MODE))|\s*$)/i);
645648
if (groupByMatch) {
646649
const groupByClause = groupByMatch[1].trim();
647650
this.groupByFields = groupByClause.split(',').map(field => field.trim());
648651
}
649652
}
650653

651654
parseHavingClause(query) {
652-
const havingMatch = query.match(/HAVING\s+(.*?)(?:\s+(?:ORDER\s+BY|LIMIT|OFFSET|FOR\s+(?:UPDATE|VIEW|REFERENCE)|ALL\s+ROWS)\s|$)/i);
655+
const havingMatch = query.match(/HAVING\s+(.*?)(?:\s+(?:ORDER\s+BY|LIMIT|OFFSET|FOR\s+(?:UPDATE|VIEW|REFERENCE)|ALL\s+ROWS|WITH\s+(?:USER_MODE|SYSTEM_MODE))|\s*$)/i);
653656
if (havingMatch) {
654657
const havingClause = havingMatch[1].trim();
655658
this.havingConditions = [havingClause];
@@ -677,7 +680,7 @@ class SOQLToSOQLLibTranslator {
677680
}
678681
}
679682

680-
generateSOQLLibCode() {
683+
generateSOQLLibCode(hasSystemMode = false) {
681684
let code = `SOQL.of(${this.sobjectType}.SObjectType)`;
682685

683686
// Handle SELECT fields
@@ -823,6 +826,12 @@ class SOQLToSOQLLibTranslator {
823826
}
824827
}
825828

829+
// Add system mode when WITH SYSTEM_MODE is specified in the query
830+
if (hasSystemMode) {
831+
code += '\n .systemMode()';
832+
code += '\n .withoutSharing()';
833+
}
834+
826835
// Add result method
827836
code += '\n .toList();';
828837

@@ -1103,11 +1112,21 @@ FROM Account
11031112
WHERE Industry = 'Technology'
11041113
AND BillingCity = 'San Francisco'
11051114
ORDER BY Name ASC
1106-
LIMIT 10`);
1115+
LIMIT 10
1116+
WITH USER_MODE`);
11071117

11081118
const [soqlLibOutput, setSoqlLibOutput] = useState('');
11091119
const [isLoading, setIsLoading] = useState(false);
11101120

1121+
// Trigger syntax highlighting when output changes
1122+
useEffect(() => {
1123+
if (typeof window !== 'undefined' && window.Prism && soqlLibOutput) {
1124+
setTimeout(() => {
1125+
window.Prism.highlightAll();
1126+
}, 100);
1127+
}
1128+
}, [soqlLibOutput]);
1129+
11111130
const translator = new SOQLToSOQLLibTranslator();
11121131

11131132
const handleTranslate = () => {
@@ -1134,65 +1153,118 @@ LIMIT 10`);
11341153
};
11351154

11361155
const examples = [
1137-
{
1138-
name: "Simple Query",
1139-
query: `SELECT Id, Name FROM Account WHERE Name LIKE '%Test%'`
1140-
},
1156+
{
1157+
name: "Simple Query",
1158+
query: `SELECT Id, Name
1159+
FROM Account
1160+
WHERE Name LIKE '%Test%'
1161+
WITH USER_MODE`
1162+
},
11411163
{
11421164
name: "Multiple Conditions",
1143-
query: `SELECT Id, Name, Owner.Name FROM Account WHERE Industry = 'Technology' AND BillingCity = 'San Francisco'`
1165+
query: `SELECT Id, Name, Owner.Name
1166+
FROM Account
1167+
WHERE Industry = 'Technology'
1168+
AND BillingCity = 'San Francisco'
1169+
WITH USER_MODE`
11441170
},
11451171
{
11461172
name: "OR Conditions",
1147-
query: `SELECT Id, Name FROM Account WHERE Industry = 'Technology' OR Industry = 'Healthcare'`
1173+
query: `SELECT Id, Name
1174+
FROM Account
1175+
WHERE Industry = 'Technology'
1176+
OR Industry = 'Healthcare'
1177+
WITH USER_MODE`
11481178
},
11491179
{
11501180
name: "Parent Fields",
1151-
query: `SELECT Id, Name, CreatedBy.Id, CreatedBy.Name, Parent.Id, Parent.Name FROM Account`
1152-
},
1153-
{
1154-
name: "Aggregate Query",
1155-
query: `SELECT Industry, COUNT(Id) total FROM Account GROUP BY Industry HAVING COUNT(Id) > 5`
1181+
query: `SELECT Id, Name, CreatedBy.Id, CreatedBy.Name, Parent.Id, Parent.Name
1182+
FROM Account
1183+
WITH USER_MODE`
11561184
},
11571185
{
11581186
name: "COUNT & SUM",
1159-
query: `SELECT CampaignId, COUNT(Id) totalRecords, SUM(Amount) totalAmount FROM Opportunity GROUP BY CampaignId`
1187+
query: `SELECT CampaignId, COUNT(Id) totalRecords, SUM(Amount) totalAmount
1188+
FROM Opportunity
1189+
GROUP BY CampaignId
1190+
WITH USER_MODE`
11601191
},
11611192
{
11621193
name: "AVG & MIN",
1163-
query: `SELECT Industry, AVG(AnnualRevenue) avgRevenue, MIN(NumberOfEmployees) minEmployees FROM Account GROUP BY Industry`
1194+
query: `SELECT Industry, AVG(AnnualRevenue) avgRevenue, MIN(NumberOfEmployees) minEmployees
1195+
FROM Account
1196+
GROUP BY Industry
1197+
WITH USER_MODE`
11641198
},
11651199
{
11661200
name: "SubQuery",
1167-
query: `SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account`
1201+
query: `SELECT Id, Name, (SELECT Id, Name FROM Contacts)
1202+
FROM Account
1203+
WITH USER_MODE`
11681204
},
11691205
{
11701206
name: "Complex WHERE",
1171-
query: `SELECT Id FROM Account WHERE Industry = 'IT' AND ((Name = 'My Account' AND NumberOfEmployees >= 10) OR (Name = 'My Account 2' AND NumberOfEmployees <= 20))`
1207+
query: `SELECT Id
1208+
FROM Account
1209+
WHERE Industry = 'IT'
1210+
AND ((Name = 'My Account' AND NumberOfEmployees >= 10)
1211+
OR (Name = 'My Account 2' AND NumberOfEmployees <= 20))
1212+
WITH USER_MODE`
11721213
},
11731214
{
11741215
name: "LIKE Patterns",
1175-
query: `SELECT Id, Name FROM Account WHERE Name LIKE 'Test%' AND BillingCity LIKE '%Francisco%'`
1216+
query: `SELECT Id, Name
1217+
FROM Account
1218+
WHERE Name LIKE 'Test%'
1219+
AND BillingCity LIKE '%Francisco%'
1220+
WITH USER_MODE`
11761221
},
11771222
{
11781223
name: "IN Operator",
1179-
query: `SELECT Id, Name FROM Account WHERE Industry IN ('Technology', 'Healthcare', 'Finance')`
1224+
query: `SELECT Id, Name
1225+
FROM Account
1226+
WHERE Industry IN ('Technology', 'Healthcare', 'Finance')
1227+
WITH USER_MODE`
11801228
},
11811229
{
11821230
name: "ORDER BY Multiple",
1183-
query: `SELECT Id, Name, Industry FROM Account ORDER BY Name DESC, Industry ASC LIMIT 50`
1231+
query: `SELECT Id, Name, Industry
1232+
FROM Account
1233+
ORDER BY Name DESC, Industry ASC
1234+
LIMIT 50
1235+
WITH USER_MODE`
11841236
},
11851237
{
11861238
name: "Complex Query",
1187-
query: `SELECT Id, Name FROM Account WHERE (Industry = 'Technology' OR Industry = 'Healthcare') AND NumberOfEmployees > 100 ORDER BY Name LIMIT 20`
1239+
query: `SELECT Id, Name
1240+
FROM Account
1241+
WHERE (Industry = 'Technology' OR Industry = 'Healthcare')
1242+
AND NumberOfEmployees > 100
1243+
ORDER BY Name
1244+
LIMIT 20
1245+
WITH USER_MODE`
11881246
},
11891247
{
11901248
name: "Boolean Fields",
1191-
query: `SELECT Id, Name FROM Account WHERE IsDeleted = false AND IsPersonAccount = true`
1249+
query: `SELECT Id, Name
1250+
FROM Account
1251+
WHERE IsDeleted = false
1252+
AND IsPersonAccount = true
1253+
WITH USER_MODE`
11921254
},
11931255
{
11941256
name: "NULL Checks",
1195-
query: `SELECT Id, Name FROM Account WHERE ParentId != null AND BillingCity = null`
1257+
query: `SELECT Id, Name
1258+
FROM Account
1259+
WHERE ParentId != null
1260+
AND BillingCity = null
1261+
WITH USER_MODE`
1262+
},
1263+
{
1264+
name: "System Mode",
1265+
query: `SELECT Id, Name, CreatedBy.Id, CreatedBy.Name, Parent.Id, Parent.Name
1266+
FROM Account
1267+
WITH SYSTEM_MODE`
11961268
}
11971269
];
11981270

@@ -1208,7 +1280,7 @@ LIMIT 10`);
12081280
<div className="container mx-auto px-4 py-8 max-w-7xl">
12091281
<div className="text-center mb-8">
12101282
<Heading as="h1" className="text-4xl font-bold mb-4">
1211-
SOQL to SOQL Lib Playground
1283+
SOQL Lib Playground
12121284
</Heading>
12131285
<p className="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
12141286
Paste your traditional SOQL query and see how it translates to SOQL Lib syntax.
@@ -1232,31 +1304,31 @@ LIMIT 10`);
12321304
</div>
12331305
</div>
12341306

1235-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
1307+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 items-start">
12361308
{/* Input Panel */}
1237-
<div className="space-y-4">
1309+
<div className="space-b-4 h-full">
12381310
<div className="flex items-center justify-between">
12391311
<h2 className="text-xl font-semibold">Traditional SOQL</h2>
12401312
<button
12411313
onClick={handleClear}
1242-
className="px-3 py-1 text-sm bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 rounded transition-colors"
1314+
className="px-3 py-1 text-sm bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 rounded transition-colors border-none"
12431315
>
12441316
Clear
12451317
</button>
12461318
</div>
12471319
<textarea
12481320
value={soqlInput}
12491321
onChange={(e) => setSoqlInput(e.target.value)}
1250-
className="w-full h-64 p-4 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 font-mono text-sm resize-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
1322+
className="w-full h-80 p-4 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 font-mono text-sm resize-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
12511323
placeholder="Enter your SOQL query here..."
12521324
/>
12531325
</div>
12541326

12551327
{/* Output Panel */}
1256-
<div className="space-y-4">
1328+
<div className="space-y-4 h-full">
12571329
<h2 className="text-xl font-semibold">SOQL Lib Syntax</h2>
12581330
<div className="relative">
1259-
<pre className="w-full h-64 p-4 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-900 font-mono text-sm overflow-auto">
1331+
<pre className="w-full h-80 p-4 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-900 font-mono text-sm overflow-auto">
12601332
<code className="language-java">{soqlLibOutput || '// Your translated SOQL Lib code will appear here...'}</code>
12611333
</pre>
12621334
{soqlLibOutput && (
@@ -1296,21 +1368,21 @@ LIMIT 10`);
12961368
{/* Info Section */}
12971369
<div className="mt-12 p-6 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
12981370
<h3 className="text-lg font-semibold mb-3">💡 How it works</h3>
1299-
<ul className="space-y-2 text-sm text-gray-700 dark:text-gray-300">
1300-
<li><strong>Field Selection:</strong> Converts SELECT fields to <code>.with()</code> methods</li>
1301-
<li><strong>Relationships:</strong> Transforms parent.field syntax to <code>.with('Parent', fields)</code></li>
1302-
<li><strong>WHERE Conditions:</strong> Parses conditions into <code>SOQL.Filter</code> and <code>SOQL.FilterGroup</code></li>
1303-
<li><strong>Filter Operations:</strong> Maps SOQL operators to methods like <code>.equal()</code>, <code>.contains()</code>, <code>.greaterThan()</code></li>
1304-
<li><strong>Logic Operators:</strong> AND conditions are grouped, OR uses <code>.anyConditionMatching()</code></li>
1305-
<li><strong>Aggregate Functions:</strong> Maps to specific methods like <code>.count()</code>, <code>.sum()</code></li>
1306-
<li><strong>ORDER BY:</strong> Translates to <code>.orderBy()</code> with direction methods</li>
1307-
<li><strong>LIMIT/OFFSET:</strong> Converts to <code>.setLimit()</code> and <code>.offset()</code></li>
1308-
</ul>
1371+
<ul className="space-y-2 text-sm text-gray-700 dark:text-gray-300">
1372+
<li><strong>Field Selection:</strong> Converts SELECT fields to <code>.with()</code> methods - <a href="/soql/api/soql#with" className="text-blue-600 hover:text-blue-800 underline">API docs</a></li>
1373+
<li><strong>Relationships:</strong> Transforms parent.field syntax to <code>.with('Parent', fields)</code> - <a href="/soql/api/soql#with-related-field" className="text-blue-600 hover:text-blue-800 underline">API docs</a></li>
1374+
<li><strong>WHERE Conditions:</strong> Parses conditions into <code>SOQL.Filter</code> and <code>SOQL.FilterGroup</code> - <a href="/soql/api/soql-filter" className="text-blue-600 hover:text-blue-800 underline">Filter API</a> | <a href="/soql/api/soql-filters-group" className="text-blue-600 hover:text-blue-800 underline">FilterGroup API</a></li>
1375+
<li><strong>Filter Operations:</strong> Maps SOQL operators to methods like <code>.equal()</code>, <code>.contains()</code>, <code>.greaterThan()</code> - <a href="/soql/api/soql-filter#comparators" className="text-blue-600 hover:text-blue-800 underline">API docs</a></li>
1376+
<li><strong>Logic Operators:</strong> AND conditions are grouped, OR uses <code>.anyConditionMatching()</code> - <a href="/soql/api/soql-filters-group#anyconditionmatching" className="text-blue-600 hover:text-blue-800 underline">API docs</a></li>
1377+
<li><strong>Aggregate Functions:</strong> Maps to specific methods like <code>.count()</code>, <code>.sum()</code> - <a href="/soql/api/soql#aggregate-functions" className="text-blue-600 hover:text-blue-800 underline">API docs</a></li>
1378+
<li><strong>ORDER BY:</strong> Translates to <code>.orderBy()</code> with direction methods - <a href="/soql/api/soql#order-by" className="text-blue-600 hover:text-blue-800 underline">API docs</a></li>
1379+
<li><strong>LIMIT/OFFSET:</strong> Converts to <code>.setLimit()</code> and <code>.offset()</code> - <a href="/soql/api/soql#limit" className="text-blue-600 hover:text-blue-800 underline">LIMIT</a> | <a href="/soql/api/soql#offset" className="text-blue-600 hover:text-blue-800 underline">OFFSET</a></li>
1380+
</ul>
13091381

13101382
<p className="mt-4 text-sm text-gray-600 dark:text-gray-400">
13111383
<strong>Note:</strong> This is a learning tool that covers most common SOQL patterns.
13121384
Complex nested conditions may need manual refinement. Check the
1313-
<a href="/soql/getting-started" className="text-blue-600 hover:text-blue-800 underline"> full documentation</a> for advanced features.
1385+
<a href="/soql/examples/select" className="text-blue-600 hover:text-blue-800 underline"> full documentation</a> for advanced features.
13141386
</p>
13151387
</div>
13161388
</div>

0 commit comments

Comments
 (0)