22 * Copyright (c) 2025 Beyond The Cloud Sp. z o.o. (BeyondTheCloud.Dev)
33 * Licensed under the MIT License (https://github.com/beyond-the-cloud-dev/soql-lib/blob/main/LICENSE)
44 *
5- * v6.6 .0
5+ * v6.7 .0
66 *
77 * PMD False Positives:
88 * - ExcessivePublicCount: It is a library class and exposes all necessary methods to construct a query
@@ -159,6 +159,8 @@ global virtual inherited sharing class SOQL implements Queryable {
159159 Integer toInteger ();
160160 // QUERY LOCATOR
161161 Database.QueryLocator toQueryLocator ();
162+ // CURSOR
163+ Database.Cursor toCursor ();
162164 // DO EXIST
163165 Boolean doExist ();
164166 // AGGREGATE RESULTS
@@ -273,8 +275,10 @@ global virtual inherited sharing class SOQL implements Queryable {
273275 Filter notStartsWith (String value );
274276 Filter isIn (Iterable <Object > iterable );
275277 Filter isIn (InnerJoin joinQuery );
278+ Filter isIn (Iterable <SObject > sourceRecords , SObjectField sourceKeyField );
276279 Filter notIn (Iterable <Object > iterable );
277280 Filter notIn (InnerJoin joinQuery );
281+ Filter notIn (Iterable <SObject > sourceRecords , SObjectField sourceKeyField );
278282 Filter includesAll (Iterable <String > values );
279283 Filter includesSome (Iterable <String > values );
280284 Filter excludesAll (Iterable <String > values );
@@ -397,6 +401,10 @@ global virtual inherited sharing class SOQL implements Queryable {
397401
398402 // Mocking
399403
404+ global static Mockable mock (SObjectType ofObject ) {
405+ return mock (ofObject .toString ().hashCode ().toString ());
406+ }
407+
400408 global static Mockable mock (String mockId ) {
401409 if (! SOQL .queryIdToMock .containsKey (mockId )) {
402410 SOQL .queryIdToMock .put (mockId , new List <SoqlMock >());
@@ -463,6 +471,8 @@ global virtual inherited sharing class SOQL implements Queryable {
463471 this .builder = new SoqlBuilder (ofObject );
464472 this .executor = new Executor (builder );
465473 this .converter = new Converter (ofObject );
474+
475+ this .mockId (ofObject .hashCode ().toString ());
466476 }
467477
468478 global Queryable with (SObjectField field ) {
@@ -1100,6 +1110,10 @@ global virtual inherited sharing class SOQL implements Queryable {
11001110 return this .executor .toQueryLocator ();
11011111 }
11021112
1113+ global Database.Cursor toCursor () {
1114+ return this .executor .toCursor ();
1115+ }
1116+
11031117 global Queryable byId (SObject record ) {
11041118 return this .byId (record .Id );
11051119 }
@@ -1858,6 +1872,10 @@ global virtual inherited sharing class SOQL implements Queryable {
18581872 return this .set (' IN' , joinQuery );
18591873 }
18601874
1875+ public Filter isIn (Iterable <SObject > sourceRecords , SObjectField sourceKeyField ) {
1876+ return this .isIn (this .extractValues (sourceRecords , sourceKeyField ));
1877+ }
1878+
18611879 private Filter notLike () {
18621880 this .wrapper = ' (NOT {0})' ;
18631881 return this ;
@@ -1872,6 +1890,24 @@ global virtual inherited sharing class SOQL implements Queryable {
18721890 return this .set (' NOT IN' , joinQuery );
18731891 }
18741892
1893+ public Filter notIn (Iterable <SObject > sourceRecords , SObjectField sourceKeyField ) {
1894+ return this .notIn (this .extractValues (sourceRecords , sourceKeyField ));
1895+ }
1896+
1897+ private List <String > extractValues (Iterable <SObject > sourceRecords , SObjectField sourceKeyField ) {
1898+ List <String > values = new List <String >();
1899+
1900+ for (SObject sourceRecord : sourceRecords ) {
1901+ if (sourceRecord ?. get (sourceKeyField ) == null ) {
1902+ continue ;
1903+ }
1904+
1905+ values .add (sourceRecord .get (sourceKeyField ).toString ());
1906+ }
1907+
1908+ return values ;
1909+ }
1910+
18751911 public Filter includesAll (Iterable <String > iterable ) {
18761912 return this .setMultipicklistFilter (' INCLUDES' , iterable , ' ;' );
18771913 }
@@ -2772,6 +2808,11 @@ global virtual inherited sharing class SOQL implements Queryable {
27722808 return this .sharingExecutor .toQueryLocator (this .builder .toString (), binder .getBindingMap (), this .accessMode );
27732809 }
27742810
2811+ public Database.Cursor toCursor () {
2812+ this .incrementQueryIssued ();
2813+ return sharingExecutor .toCursor (builder .toString (), binder .getBindingMap (), accessMode );
2814+ }
2815+
27752816 private void incrementQueryIssued () {
27762817 // This counter is used only in unit tests to also track mocked queries.
27772818 if (! System .Test .isRunningTest () || System .isBatch () || System .isFuture () || System .isQueueable () || System .isScheduled ()) {
@@ -2792,6 +2833,7 @@ global virtual inherited sharing class SOQL implements Queryable {
27922833 List <SObject > toSObjects (String query , Map <String , Object > binding , AccessLevel accessLevel );
27932834 Integer toInteger (String query , Map <String , Object > binding , AccessLevel accessLevel );
27942835 Database.QueryLocator toQueryLocator (String query , Map <String , Object > binding , AccessLevel accessLevel );
2836+ Database.Cursor toCursor (String query , Map <String , Object > binding , AccessLevel accessLevel );
27952837 }
27962838
27972839 private inherited sharing class InheritedSharing implements DatabaseQuery {
@@ -2806,6 +2848,10 @@ global virtual inherited sharing class SOQL implements Queryable {
28062848 public Database.QueryLocator toQueryLocator (String query , Map <String , Object > binding , AccessLevel accessLevel ) {
28072849 return Database .getQueryLocatorWithBinds (query , binding , accessLevel );
28082850 }
2851+
2852+ public Database.Cursor toCursor (String query , Map <String , Object > binding , AccessLevel accessLevel ) {
2853+ return Database .getCursorWithBinds (query , binding , accessLevel );
2854+ }
28092855 }
28102856
28112857 private without sharing class WithoutSharing implements DatabaseQuery {
@@ -2820,6 +2866,10 @@ global virtual inherited sharing class SOQL implements Queryable {
28202866 public Database.QueryLocator toQueryLocator (String query , Map <String , Object > binding , AccessLevel accessLevel ) {
28212867 return Database .getQueryLocatorWithBinds (query , binding , accessLevel );
28222868 }
2869+
2870+ public Database.Cursor toCursor (String query , Map <String , Object > binding , AccessLevel accessLevel ) {
2871+ return Database .getCursorWithBinds (query , binding , accessLevel );
2872+ }
28232873 }
28242874
28252875 private with sharing class WithSharing implements DatabaseQuery {
@@ -2834,6 +2884,10 @@ global virtual inherited sharing class SOQL implements Queryable {
28342884 public Database.QueryLocator toQueryLocator (String query , Map <String , Object > binding , AccessLevel accessLevel ) {
28352885 return Database .getQueryLocatorWithBinds (query , binding , accessLevel );
28362886 }
2887+
2888+ public Database.Cursor toCursor (String query , Map <String , Object > binding , AccessLevel accessLevel ) {
2889+ return Database .getCursorWithBinds (query , binding , accessLevel );
2890+ }
28372891 }
28382892
28392893 public inherited sharing class Converter {
0 commit comments