diff --git a/debug/test.js b/debug/test.js index bd9c49b..7c3b81d 100644 --- a/debug/test.js +++ b/debug/test.js @@ -1,7 +1,7 @@ var soqlParserJs = require('../dist'); const query = ` -SELECT Company, toLabel(Status) FROM Lead WHERE toLabel(Status) = 'le Draft' +SELECT Account.Name, (SELECT Contact.LastName FROM Account.Contact.Foo.Bars) FROM Account `; const parsedQuery = soqlParserJs.parseQuery(query, { logging: true }); diff --git a/lib/SoqlComposer.ts b/lib/SoqlComposer.ts index c669931..3f5b9da 100644 --- a/lib/SoqlComposer.ts +++ b/lib/SoqlComposer.ts @@ -62,7 +62,7 @@ export class Compose { fields.forEach((field, i) => { if (field.match(this.subqueryFieldRegex)) { const subquery = query.subqueries.find( - subquery => subquery.sObject === field.replace(this.subqueryFieldReplaceRegex, '') + subquery => subquery.sObjectRelationshipName === field.replace(this.subqueryFieldReplaceRegex, '') ); if (subquery) { fields[i] = `(${this.parseQuery(subquery)})`; @@ -70,7 +70,13 @@ export class Compose { } }); output += ` ${fields.join(', ').trim()} FROM`; - output += ` ${utils.get(query.sObjectPrefix, '.')}${query.sObject}${utils.get(query.sObjectAlias, '', ' ')}`; + if (query.sObjectRelationshipName) { + const sObjectPrefix = query.sObjectPrefix || []; + sObjectPrefix.push(query.sObjectRelationshipName); + output += ` ${sObjectPrefix.join('.')}${utils.get(query.sObjectAlias, '', ' ')}`; + } else { + output += ` ${query.sObject}${utils.get(query.sObjectAlias, '', ' ')}`; + } this.log(output); if (query.where) { diff --git a/lib/SoqlListener.ts b/lib/SoqlListener.ts index 239524f..aefff9c 100644 --- a/lib/SoqlListener.ts +++ b/lib/SoqlListener.ts @@ -844,11 +844,20 @@ export class Listener implements SOQLListener { if (this.config.logging) { console.log('enterObject_spec:', ctx.text); } - this.getSoqlQuery().sObject = ctx.getChild(0).text; - if (this.config.includeSubqueryAsField && this.context.isSubQuery) { + + if (!this.context.isSubQuery) { + this.getSoqlQuery().sObject = ctx.getChild(0).text; + } else { + this.getSoqlQuery().sObjectRelationshipName = ctx.getChild(0).text; if (ctx.getChild(0).text.includes('.')) { - this.getSoqlQuery().sObject = ctx.getChild(1).text; - this.getSoqlQuery().sObjectPrefix = ctx.getChild(0).text.replace('.', ''); + this.getSoqlQuery().sObjectRelationshipName = ctx.getChild(1).text; + const prefixList: string[] = []; + for (let i = 0; i < ctx.getChild(0).childCount; i++) { + if (ctx.getChild(0).getChild(i) instanceof Parser.Object_nameContext) { + prefixList.push(ctx.getChild(0).getChild(i).text); + } + } + this.getSoqlQuery().sObjectPrefix = prefixList; this.soqlQuery.fields.push({ subqueryObjName: ctx.getChild(1).text, }); diff --git a/lib/models/SoqlQuery.model.ts b/lib/models/SoqlQuery.model.ts index eb8fc2d..eb05f13 100644 --- a/lib/models/SoqlQuery.model.ts +++ b/lib/models/SoqlQuery.model.ts @@ -9,9 +9,10 @@ export type UpdateClause = 'TRACKING' | 'VIEWSTAT'; export interface Query { fields: Field[]; subqueries: Query[]; - sObject: string; + sObject?: string; sObjectAlias?: string; - sObjectPrefix?: string; + sObjectPrefix?: string[]; + sObjectRelationshipName?: string; where?: WhereClause; limit?: number; offset?: number; diff --git a/test/TestCases.ts b/test/TestCases.ts index 74b6d79..a06c981 100644 --- a/test/TestCases.ts +++ b/test/TestCases.ts @@ -306,7 +306,7 @@ export const testCases: TestCase[] = [ }, ], subqueries: [], - sObject: 'Contacts', + sObjectRelationshipName: 'Contacts', }, ], sObject: 'Account', @@ -334,8 +334,8 @@ export const testCases: TestCase[] = [ }, ], subqueries: [], - sObject: 'Contacts', - sObjectPrefix: 'Account', + sObjectRelationshipName: 'Contacts', + sObjectPrefix: ['Account'], }, ], sObject: 'Account', @@ -362,7 +362,7 @@ export const testCases: TestCase[] = [ }, ], subqueries: [], - sObject: 'Contacts', + sObjectRelationshipName: 'Contacts', where: { left: { field: 'CreatedBy.Alias', @@ -430,7 +430,7 @@ export const testCases: TestCase[] = [ }, ], subqueries: [], - sObject: 'Line_Items__r', + sObjectRelationshipName: 'Line_Items__r', }, ], sObject: 'Merchandise__c', @@ -565,7 +565,7 @@ export const testCases: TestCase[] = [ }, ], subqueries: [], - sObject: 'Notes', + sObjectRelationshipName: 'Notes', }, ], sObject: 'Account', @@ -609,7 +609,7 @@ export const testCases: TestCase[] = [ }, ], subqueries: [], - sObject: 'OpportunityLineItems', + sObjectRelationshipName: 'OpportunityLineItems', }, ], sObject: 'Opportunity', @@ -1007,7 +1007,7 @@ export const testCases: TestCase[] = [ }, ], subqueries: [], - sObject: 'ChildAccounts', + sObjectRelationshipName: 'ChildAccounts', sObjectAlias: 'a2', }, { @@ -1018,7 +1018,7 @@ export const testCases: TestCase[] = [ }, ], subqueries: [], - sObject: 'ChildAccounts1', + sObjectRelationshipName: 'ChildAccounts1', sObjectAlias: 'a1', }, ], @@ -1440,5 +1440,34 @@ export const testCases: TestCase[] = [ }, }, }, + { + testCase: 50, + soql: 'SELECT Account.Name, (SELECT Contact.LastName FROM Account.Contact.Foo.Bars) FROM Account', + output: { + fields: [ + { + text: 'Account.Name', + relationshipFields: ['Account', 'Name'], + }, + { + subqueryObjName: 'Bars', + }, + ], + subqueries: [ + { + fields: [ + { + text: 'Contact.LastName', + relationshipFields: ['Contact', 'LastName'], + }, + ], + subqueries: [], + sObjectRelationshipName: 'Bars', + sObjectPrefix: ['Account', 'Contact', 'Foo'], + }, + ], + sObject: 'Account', + }, + }, ]; export default testCases;