Salesforce Developer Helper

Thursday, May 21, 2015

Dynamic Search (SOSL)

Dynamic Search refers to the creation of a SOSL string at run time with Apex code. It enables you to create more flexible applications. For example, you can create a search based on input from an end user, or update records with varying field names. To create a dynamic search (SOSL) query at run time, use the search query method. List<List<sObject>> searchResults = search.query(SOSL_search_string);
  • SOSL is supported only in apex class and the anonymous block.
  • SOSL can not be used in apex trigger.
  • If SOSL does not return any records for a specified saelsforce object type, and the result for that sObject type is empty list


The following example a simple SOSL query string.
String soslString='FIND\'Edge*\'IN ALL FIELDS RETURNING Account(id,name,BillingCity),Contact, Lead'; 
List<List<SObject>>searchList=search.query(soslString);
List<Account> accounts = (List<Account>)searchList.get(0);
List<Contact> contacts = (List<Contact>)searchList.get(1);
List<Lead> leads = (List<Lead>)searchList.get(2);
The result lists are always returned in the same order as they were specified in the dynamic SOSL query. From the example above, the results from Account are first index(0), then Contact, then Lead.

Bind Variable in Dynamic SOSL
You can use bind variables in dynamic SOSL string as the following:
This code finds cases which are description contains CASE1 or CASE2 and Account ID is 0019000000NCTyt
String filters ='CASE1 OR CASE2';
String accountID='0019000000NCTyt';

//Account is relationship name of lookup field AccountId on Case
String sosl='FIND:filters IN ALL FIELDS RETURNING Case(id,Subject,Description WHERE Account.Id=:accountID)';
List<List<SObject>> result=search.query(sosl);
System.debug('Result:'+result);

Result:((Case:{Description=Hello, This is CASE2, AccountId=0019000000NCTytAAH, Subject=test CASE2, Id=5009000000pMe00AAC}, Case:{Description=Hello, This is CASE1, AccountId=0019000000NCTytAAH, Subject=Test CASE1, Id=5009000000pMdxBAAS}))

Wednesday, May 20, 2015

Dynamic Query (SOQL)

Dynamic Query (SOQL) refers to the creation of a SOQL string at runtime with Apex code. Dynamic Query enables you to create more flexible applications. For example, you can create a search based on input from an end user, or update records with varying field names. To create dynamic query, use the database query method (e.g Database.query('string_soql')) in one of the following examples:
1. Return single sObject when the query method is executed
sObject obj = Database.query('string_limit_1');
Account acc =Database.query('select id, Name, billingCity from Account  LIMIT 1');
2. Return list of sObjects method when the query method is executed
List<sObject> objList = Database.query('string');
List<Account> accList = Database.query('select id, Name, billingCity from Account');
3. Query method in for loops
for(Account acc : Database.query('select id, Name from Account'))
{
System.debug(acc.Name);
}
The database query method can be used wherever an inline SOQL query can be used, such as in regular assignment statements and for loops. The results are processed in much the same way as static SOQL queries are processed.

Bind Variable in Dynamic Query
You can use simple bind variables in dynamic query strings. The following is allowed:
String myTestString = 'TestName';
List<sObject>
sobjList = Database.query('SELECT Id FROM CustomObject__c WHERE Name =:myTestString');
//Variable as collection
Set<String> names= new Set<String>{‘Test1’,’Test2’};
List<sObject> sobjList = Database.query('SELECT Id FROM CustomObject__c WHERE Name IN :names');
Note:
SOQL injection can occur in Apex code whenever your application relies on end user input to construct a dynamic SOQL statement and you do not handle the input properly
To prevent SOQL injection, use the String.escapeSingleQuotes(stringToEscape) method. This method adds the escape character (\) to all single quotation marks in a string that is passed in from a user.
Dynamic query can’t use bind variable fields in the query string. The following example isn’t supported and results in a Variable does not exist error:
CustomObject__c cObj= new CustomObject__c(field1__c ='TestField');
List<sObject>
sobjList = Database.query('SELECT Id FROM CustomObject__c WHERE field1__c =
:cObj.field1__c');
The following is how to construct a dynamic SOQL statement
//inputName's data contains single quote
String inputName='Test\'s Acme';
DateTime dt = System.now();

String soql='select id,Name FROM Account';

//:dt binding variable
String whereClause=' WHERE lastmodifiedDate=:dt ';
if(String.isNotBlank(inputName)){
    //escape single quote
    whereClause+='AND Name =\''+  String.escapeSingleQuotes(inputName)    +'\'';
}

soql+=whereClause;

List<Account> accounts = Database.query(soql);

Friday, May 15, 2015

Apex Data Types

Primitive Data Types
All these types are passed by values and initialized to null, Whether they are class's member or method variable. Make sure you initialize to appropriate value before using them.

Boolean flag = true;
Integer i = 2;
Double d = 3.14159;
Decimal n = d or n = i; //This type include decimal point
Long l = 2147483648L;
Object obj = 10;
Integer i = (Integer)obj;
MyApexClass o = (MyApexClass)obj;
o.myMethod();
String s = 'Hello World';
ID accountId = '001XXXXXXXXXXXXXXX';
sObject Types
Any object can be stored in salesforce database.
An sObject represents a row of data.
Account a = new Account(Name = 'Test', ...);
MyCustomObject__c cusObj = new MyCustomObject__c(Name = 'Test', ...);
sObject sObj = new Account();
Account acc = (Account)sObj;
User Defined Types
Refers to classes and interfaces in apex
MyApexClass obj = new MyApexClas();
MyApexInterface obj = new MyApexClassImplemented();
Collection Types:
Lists
A list is an order of collection elements that are distinguished by their indices. List element can be of any data types - primitive data types, collections, sObjects, user-defined types and built-in Apex types. For example:
To declare a list, use the List keyword followed by the primitive data, sObject, nested list, map of set type within <> characters. For example:
// Create an empty list of String
List<String> my_list =  new List<String>; //or new String[0];
// Create an empty list of Account
Account[] accs = new  Account[0];
List<Account> lAcc = new List<Account>();
//Create an empty list of user-defined type
List<MyApexClass> myApexs = new List<MyApexClass>();
//Create nested list
List<List<List<Integer>>> nestedList= new List<List<List<Integer>>>();
To access element in list, use the list methods provided by Apex. For example:
my_list.add('Red');
my_list.add('Orange');
System.assertEquals('Orange', my_list.get(1));
You can populate list elements when the list is declared by using curly brace ({})
List<String> lst = new List<String> {'Red','Orange', ...};
System.assertEquals('Red', lst [0]);
System.assertEquals('Orange', lst.get(1));
List<Account> accounts=[select id,name from Account];
You can create new instance of the List class by copying the elements from specific list.
List<String> my_list1 = new List<String>{'Red','Orange'};
List<String> my_list2 = new List<String>(my_list1 );
You can create new instance of the List class by copying the elements from specific set.
Set<Integer> setInts = new Set<Integer>{1,2,3};
List<Integer> myIntegers= new List<Integer>(setInts);
Sets
A set is an unordered collection of elements that do not contain any duplicates. Set elements can be of any data type—primitive types, collections, sObjects, user-defined types, and built-in Apex types. For example, the following table represents a set of strings, that uses city names:
'San Francisco', 'New York' 'Paris' 'Tokyo'
Sets can contain collections that can be nested within one another. For example, you can have a set of lists of sets of Integers. A set can contain up to four levels of nested collections inside it, that is, up to five levels overall.
To declare a set, use the Set keyword followed by the primitive data type name within <> characters. For example:
Set<String> mySet = new Set<String>();
You can populate elements when the set is declared by using curly brace ({})
Set<String> sets = new Set<String>{'Red','Orange', 'Banana'};
Creates a new instance of the Set class by copying the elements of the specified set
Set<String> setsx= new Set<String>(sets);
To access elements in a set, use the system methods provided by Apex. For example:
Set<String> s= new Set<String>();
s.add('Apple');
System.assert(s.contains('Apple'));
s.remove('Apple');
System.assert(s.size()==0);
Creates a new instance of the Set class by coping the list elements
List<String> ls = new List<String>();
ls.add('Apple');
ls.add( 'Orange');
ls.add('Apple');
Set<String> sets =new Set<String>(ls);
System.assert(sets.size()==2);
Maps
A map is collection of key-value pairswhere each unique key maps to single value. Keys and values can be any data type - primitive data types, collections, sObjects, user-defined types and built-in Apex types. For example:
Country(key) - 'United States', 'Japan', 'France',... Currency(value) - 'Dollar', 'Yen', 'Euro',...
To declare a map, use the Map keyword followed by the data type of the key and the value within <> characters. For example:
//Map of primitive data type String
Map<String,String> country_currency = new Map<String,String>();
//Map of Account
Map<ID, Account> idAccount =new Map<ID, Account>();
//Map of sObject type, see bellow
Map<ID, sObject> idsObject = new Map<ID, sObject>(List<sObject>);
//Map of collection type Set
Map<String,Set<String>> mapCollection = new Map<String,Set<String>>();
//Map of user-defined type MyApexClass
Map<String,MyApexClass> mMyApex = new Map<String,MyApexClass>();
To access elements in a map, use the map methods provided by Apex. For example:
country_currency .put('United States',  'Dollar');
country_currency .put( 'Japan',  'Yen');
System.assertEquals(true, country_currency.containsKey('Japan'));
System.assertEquals('Yen', country_currency.get('Japan'));
You can populate map key-value pairs when the map is declared by using curly brace ({})
Map<String,String> mString= new Map<String,String>{'a' => 'Apple', 'b'='Book'};
The value for key a is Apple and b is Book.
You can create new instance of the Map class and populate it with passed-in list of sObject records. The keys are sObject IDs and the values are sObjects
List<Account> ls= [select Id,Name from Account];
Map<ID, Account> idAccountRecords = new Map<ID, Account>(ls);