jongpie / nebulaqueryandsearch Goto Github PK
View Code? Open in Web Editor NEWApex library that dynamically generates SOQL & SOSL queries
License: MIT License
Apex library that dynamically generates SOQL & SOSL queries
License: MIT License
As a person who hates SOSL as much as SOQL, I want to add support for SOSL to the framework so that I can minimize my interaction with it.
Ideally, the framework should allow switching between SOQL and SOSL with minimal or no changes to the rest of the builder methods being used.
this query
Set<Id> reportIds = new Map<Id, Misconduct_Report3__c>(miscReports).keySet();
Nebula.Query allegQuery = new Nebula.Query(Schema.Allegation__c.SObjectType)
.addFields(new List<SObjectField>{Schema.Allegation__c.Misconduct_Report__c, Schema.Allegation__c.Allegation_Type__c, Schema.Allegation__c.CreatedDate})
.includeRelatedRecords(Schema.Allegation_Review3__c.Allegation__c, reviewQuery)
.filterWhere(Schema.Allegation__c.Misconduct_Report__c.Id, Nebula.SOQL.Operator.IS_IN, reportIds);
the filterWhere method is generating the following where clause in my query
FROM Allegation__c
WHERE Id IN {a8NOC00000000BO2AY, a8NOC00000000BT2AY, a8NOC00000000BY2AY, a8NOC00000000Bd2AI, a8NOC00000000Bi2AI, a8NOC00000000Bn2AI, a8NOC00000000Bs2AI, a8NOC00000000Bx2AI, a8NOC00000000C22AI}
which is resulting in the System.QueryException expecting a colon, found '{'
I've traced this back to the SOQL.QueryArgument.formatObjectForQueryString()
method not calling the convertSetToQueryString()
method for a Set argument, but instead falling through to the terminal else clause, which just serializes the Set, resulting in the value we have above.
I really hate having each public method execute the query string - I'd much prefer that SObjectRepository handles the query execution and just returns an sobject or list of sobjects.
Currently, cached queries & query results are stored in private variables, which can quickly use up the Apex heap size. Platform cache should be used - either as a configurable secondary option, or as a complete replacement for the current approach.
This should also provide a way to leverage both org & session-level caching.
Stop being lazy
With the current implementation, if you want to query multiple fields from a parent object, the code required is somewhat lengthy:
Query accountQuery = new Query(Schema.Case.SObjectType)
.addField(new SOQL.QueryField(new List<Schema.SObjectField>{
Schema.Case.AccountId,
Schema.Account.AnnualRevenue
}))
.addField(new SOQL.QueryField(new List<Schema.SObjectField>{
Schema.Case.AccountId,
Schema.Account.NumberOfEmployees
}));
System.debug(accountQuery.getQuery());
System.debug(accountQuery.getResults());
In the above example, each parent-level field has to have the chain of fields passed to a constructor for SOQL.QueryField()
- it'd be nice if some of the field chain could be reused so Apex devs can write less code to get the same functionality.
I have a usecase where I want to create a Nebula Query instance, call a series of common method invocations on the Query, then clone the Query so I can proceed to make varying method invocations on the two versions.
Currently in order to get two Query objects that share a common core structure but vary in other ways is to manually build each Query from the ground up.
Query accountQuery = new Query(Schema.Account.SObjectType) // Query the account object
.addField(Schema.Account.Id)
.addFields(SOQL.FieldCategory.CUSTOM); // Include all custom fields - only fields that are accessible to the user are included
List accounts = accountQuery.getResults();
DEBUG| this.getQuery(): SELECT , Account_Contact_Soft_Credits_Last_Year__c FROM Account;
I am digging into getQuery()
Another example query repository class should be added for an object that is related to Lead. This will help demonstrate how to organize queries for related objects. The Task object would be a good object to use for this purpose.
Available in Spring '23 release - https://help.salesforce.com/s/articleView?id=release-notes.rn_apex_bind_var_soql.htm&type=5&release=242
Using a static query like the below example has a benefit on the Force.com platform: any custom fields referenced in the query (either in the SELECT statement or the WHERE statement) cannot be accidentally deleted. This validation occurs as soon as an admin attempts to delete the field.
[SELECT Id FROM Account Name = 'My Company']
When using dynamic SOQL, this problem can be broken down into 2 parts
The SELECT statement piece is already solved (or at least mostly solved) by using field sets - the field set itseslf cannot be deleted if referenced in Apex, and the fields in the field set cannot be deleted simply because they are in a field set.
The WHERE statement is much more difficult to solve because WHERE statements can have several different conditions, each with different operators, etc. This project doesn't currently try to handle that - the current implementation is to build the WHERE statement as a string, using the KISS principle.
We want to get the best of both worlds
I really hate random utility classes that are only used by one other class.
Some standard objects don't allow field sets to be created - to give more flexibility, there should be a second constructor for SObjectRepository that accepts List<Schema.SObjectField> as an alternative to passing a field set.
@jongpie Thanks for this useful querybuilder. I started utilizing it in my current project's soqlhandlers and I see at the moment 2 areas for improvement: supporting subqueries and typeof in case of polymorf relationships. What is your opinion?
After years of neglect, I started rewriting this project. After a few days of work, I decided I hated it. So... my user story is
As a guy with some free time,
I want to refactor my refactor
so that it's better and I can sleep at night
The end.
PS
You say rewrite, I say refactor. You say potato, I say tomato.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.