Saturday, 17 November 2018

                                             Design Attribute In Salesforce:


Community1:
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes" access="global" >
 
    <aura:attribute name = "Name" type = "String"/>
    <aura:attribute name = "Phone" type = "String" />
    <aura:attribute name = "Position" type ="String"/>
    <p>
        Name: {!v.Name}
    </p>
    <p>
        Number: {!v.Phone}
    </p>
    <p>
        Position: {!v.Position}
    </p>
</aura:component>

Design Attributes:

<design:component  >
   <design:attribute name ="Name" label="Name"></design:attribute>
    <design:attribute name ="Phone" label="Phone Number"></design:attribute>
    <design:attribute name ="Position" label="Position" datasource = "CEO, President, Manager"></design:attribute>
</design:component>


 Design Attribute value  Specification:


If we add label for design attributes,component will change to design attribute name

<design:component label="design Practise" >
   <design:attribute name ="Name" label="Name"></design:attribute>
    <design:attribute name ="Phone" label="Phone Number"></design:attribute>
    <design:attribute name ="Position" label="Position" datasource = "CEO, President, Manager"></design:attribute>
</design:component>




Saturday, 10 November 2018


How to find the field data type of particular Object:

In this example,I had taken account as a example

String objType='Account';
Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
Schema.SObjectType leadSchema = schemaMap.get(objType);
Map<String, Schema.SObjectField> fieldMap = leadSchema.getDescribe().fields.getMap();
system.debug('field map keyset'+fieldMap.keyset());
system.debug('values###'+fieldMap.values());
for (String fieldName: fieldMap.keySet()) {
//for finding name of the field 
String fieldLabel = fieldMap.get(fieldName).getDescribe().getLabel();
 system.debug('fieldLabel>>>>>'+fieldLabel);
//get data types for each fields like string,datetime etc..
Schema.DisplayType fielddataType = fieldMap.get(fieldName).getDescribe().getType();
    //system.debug('fieldtype>>>'+fielddataType);
    if(fielddataType == Schema.DisplayType.DateTime) {
system.debug('field type*********'+fielddataType);
}
}

Saturday, 20 October 2018

Permission Subscribe to Dashboards: Add Recipients depends on permission(s): Subscribe to Dashboards

I am creating custom standard Admin profile using clone Option, I try to change field access on  custom standard Admin profile I have received the following error.

While saving:

Permission Subscribe to Dashboards: Add Recipients depends on permission(s): Subscribe to Dashboards

workaround:

1) Go to Manage Users --> User Management Settings
2) Disable the Enhanced Profile User Interface setting
3) Go back to the Profile and Save it

Wednesday, 10 October 2018


Trigger to prevent creation of duplicate accounts


trigger AccountDuplicateTrigger on Account (before update) {
//For fetching existing account names
     map<Id,Account> existingAccountMap = new  map<Id,Account>([Select Id, Name, Rating From Account]);
 for(Account a : Trigger.new){
        if(a.name = existingAccountMap.get(a.Id).Name){
          a.adderror('You cannot create a dulplicate account');
        }
     }
}

Monday, 17 September 2018

Unable to find process builder processes in change set :


You need to select Flow Definition in Component Type. Also you need to activate process builder in production after deployment.



Thursday, 13 September 2018

                             Queueable Apex:


Queueable Apex is similar to future methods, but provide additional job chaining and allow more complex data types to be used.

Queueable Apex allows you to submit jobs for asynchronous processing similar to future methods with the following additional benefits:
  • Non-primitive types: Your Queueable class can contain member variables of non-primitive data types, such as sObjects or custom Apex types. Those objects can be accessed when the job executes.
  • Monitoring: When you submit your job by invoking the System.enqueueJob method, the method returns the ID of the AsyncApexJob record. You can use this ID to identify your job and monitor its progress, either through the Salesforce user interface in the Apex Jobs page, or programmatically by querying your record from AsyncApexJob.
  • Chaining jobs: You can chain one job to another job by starting a second job from a running job. Chaining jobs is useful if you need to do some sequential processing.
---------------------------------------------------------------------------------------------------------------------
Queueable Apex:

public class QueueableExample implements Queueable {
public void execute(QueueableContext context) {
        Account a = new Account(Name='Annappa',Phone='11111111');
       insert a;     
    }
}
----------------------------------------------------------------------------------------------------------------------
Execute:

ID jobID = System.enqueueJob(new QueueableExample());
system.debug(jobId);

-------------------------------------------------------------------------------------------------------------------------

Eliminate bad code coverage data for Apex classes:


Issue: There may be times where we see a different code coverage value than the actual value. This might be caused due to bad code coverage data or aggregate results from previous test runs.

Solution: To eliminate any bad code coverage data in your organization you can follow the steps mentioned below.

For Classic:
---------------------------------------------------------------------------------
First re-run all tests in your organization: 
---------------------------------------------------------------------------------
1a) Setup | Develop | Apex Test Execution
  b) View Test History
  c) Clear test data.

2 a) Setup | Develop | Apex Classes
  b) Compile all classes

3 a) Setup | Develop | Apex Test Execution
 b) Select tests | "My Namespace" | Select all
 c) Click run

4 a) Setup | Develop | Apex Classes
  b) Estimate your organization's code coverage

  ---------------------------------------------------------------------------------
To Remove Bad data:
---------------------------------------------------------------------------------
1 a) Open Developer console
  b) Execute the following query in "Query Editor" with "Tooling API" checked.

SELECT Id, NumLinesUncovered FROM ApexCodeCoverageAggregate WHERE NumLinesUncovered = NULL

c) Select all the returned rows and hit "Delete Row"
d) Try to estimate the code coverage again
---------------------------------------------------------------------------------

                        Error while updating debug log trace flag


Some times we will receive below error while setting  debug log trace flag for user

"Having an active trace flag triggers debug logging. You have 259 MB of the maximum 250 MB of debug logs. Before you can edit trace flags, delete some debug logs."

Solution:

  • In dev console, Select tab "Query Editor" at the bottom of the console
  • Select check box "Use Tooling API"
  • Use this query: SELECT Id FROM ApexLog
  • Delete all rows

Once all rows are deleted you will be able to save new debug logs.

Monday, 3 September 2018

Replacing the Picklist old values into new values


Suppose we have a picklist (Test) which contains A,B,C values. For example A belongs to 100 records,B belongs to 200 records and C belongs to 300 records respectively.

Picklist Name: Test

A---- 100
B-----200
C-----300

Now we have new requirement: Instead of "A",we need to update with "D".This means all 100 records belongs to "A" replace with "D"



How to do it?

Using "Replace" option we can do it




Will the updated record fire Apex Triggers, Workflow Rules, etc.?

workflow rules, triggers, validation rules, flows, Process Builders, and any other logic that would run on a normal DML operation will not run as a result of using Replace.

Dynamically Determine Calling Context:

In some cases we need to Identify the calling context  whether its called from trigger,batch,future methods  etc..

These are the steps to determine it:

Batch - System.isBatch()
@future - System.isFuture()
Queueable - System.isQueueable()
Schedulable - System.isScheduled()
Trigger - Trigger.isExecuting

For example:
Consider  batch class Example:
if(System.IsBatch() == true){
    //Its calling from batch
}

More Information:

https://salesforce.stackexchange.com/questions/131140/dynamically-determine-calling-context

Wednesday, 29 August 2018

Soql Queries and Sub Queries


In the below query there are total 3 subqueries + 1 parent query. So, there are 4 queries. But, Salesforce doesn't count subqueries against governor limit of 100 SOQLs. It counts only root query which means only 1 SOQL query would be consumed.


List<Account> dd = [
    SELECT
        id,
        (SELECT Name FROM Contacts),  // <- first subquery
        (SELECT AccountID FROM Cases) // <- second subquery
    FROM
        Account
    WHERE
        id
    IN (SELECT AccountID FROM Case)   // <- not counted
];


Subqueries are counted separately as AggregateQueries. You can check those with Limits.getAggregateQueries() and Limits.getLimitAggregateQueries(). You cannot have more than 300 aggregations in a single transaction.

For example: Org contain  only 2 Account and each have 10 Contacts.

 If you execute this with sub Query like below

Select Id, Name, (Select Id, Name from Contacts) From Account

Then the total number of Query rows will be 22 (2+10+10).

 From above analogy we can understand like this:

 If your org contain 40M accounts and each have 1 contact.

Then in this scenario you can use sub query up to 25M only.

 Like this Select Id, Name, (Select Id, Name from Contacts) From Account limit 25M

Monday, 20 August 2018

will System.debug, if left in production, affect performance ?


Code executed, including System.Debug and System.assert (and their variants) have the following effects:

1) They increase debug log sizes.
2) They increase script execution time (but insignificantly).
3) They count against governor limits.

The final bullet point is your most troubling concern. A loop against 1000 records with 10 debug statements will have a total of 10,000 extra script statements than the one without.

The salesforce.com best practices state that you should always remove or comment debug statements for production code

Monday, 13 August 2018

Test.setup:



  • @testSetup ( Set Up Test Data for an Entire Test Class )Use test setup methods (methods that are annotated with @testSetup) to create test records once and then access them in every test method in the test class.
  • Test setup methods can reduce test execution times especially when you’re working with many records
  • Test setup methods enable you to create common test data easily and efficiently.
  • Test setup methods enable you to create common test data easily and efficiently.

@isTest
private class CommonTestSetup
{
 @testSetup
 static void setup()
 {
  Account acct = new Account();
       acct.Name = 'Salesforce.com';
       acct.Industry = 'Technology';
  insert acct;

  Contact cont = new Contact();
       cont.FirstName = 'Annappa';
       cont.LastName = 'ph';
       cont.AccountId = acct.Id;
  insert cont;
 }
 
 @isTest
 static void testMethod1()
 {
  Account acct = [SELECT Id FROM Account WHERE Name='Salesforce.com' LIMIT 1];
     acct.Phone = '555-1212';
  update acct;
 }

 @isTest
 static void testMethod2()
 {
  Account acct = [SELECT Phone FROM Account WHERE Name='Salesforce.com' LIMIT 1];
  System.assertEquals(null, acct.Phone);
 }
}

Note:

If a test class contains a test setup method, the test setup method executes first, before any test method in the class.
Multiple @testSetup methods are allowed in a test class, but the order in which they’re executed by the testing framework isn’t guaranteed
If the test class or a test method has access to organization data by using the @isTest(SeeAllData=true) annotation, test setup methods aren’t supported in this class.
 Date Formats and Date Literals
                                                 

DateTime field values are stored as Coordinated Universal Time (UTC).

When a dateTime value is returned in Salesforce, it’s adjusted for the time zone specified in your org preferences.

If you want to process these values in different time zones, your application might need to handle the conversion.

For a fieldExpression that uses date formats, the date is not enclosed in single quotes. Don’t use quotes around the date.

For example:

SELECT Id
FROM Account
WHERE CreatedDate > 2016-10-08T01:02:03Z

Date Literals:

Simple Queries:



 SELECT Id FROM Account WHERE CreatedDate = YESTERDAY

SELECT Id FROM Account WHERE CreatedDate > TODAY

SELECT Id FROM Opportunity WHERE CloseDate = TOMORROW

SELECT Id FROM Account WHERE CreatedDate > LAST_WEEK

SELECT Id FROM Account WHERE CreatedDate < THIS_WEEK

SELECT Id FROM Account WHERE CreatedDate < THIS_MONTH

SELECT Id FROM Account WHERE CreatedDate = LAST_90_DAYS

Saturday, 11 August 2018

Salesforce Basics :



Using same List for Update:

List<Account> acList=[select id,name from account limit 2];
system.debug('>>>acList>>>>'+acList);
for(account ac:acList){
    ac.name='Test';
}
system.debug('before update List>>'+acList);
update acList;

Here "acList" contains Updated value



Will It Updates.Parents name field?

List<Contact> contactList=[select id,accountId,account.name from contact limit 2];
for(contact c:contactList){
c.account.name='Update Parent Account';
}

update contactList;

Ans: It will not






Thursday, 19 July 2018

Apex Code Coverage Hack


Declaimer: please be aware that all things into this article are “bad practice” and should not be used constantly, it might be used for a really urgent production deployment when you have faced with a broken tests and as a result a code coverage has dropped down than 75% and you has been blocked.

As you know salesforce requires at least 75% test coverage for production deployment. You can find the following statement in documentation:

The code coverage percentage for a class or trigger displayed on the Apex Classes or the Apex Triggers page includes a fraction between parentheses with the numbers used to compute this percentage, for example, 90% (72/80). The code coverage percentage is calculated by dividing the number of lines covered by tests by the total number of lines that are part of the coverage calculation. Some lines of code are excluded from code coverage calculation, such as:


  • Comments
  • System.debug statements
  • Test methods

A code statement that is broken up into multiple lines—only the first line is counted
To generate code coverage results, you must run your Apex tests first. If no tests have been run, no code coverage data will exist and 0% (No coverage data) displays for classes (except for test classes) and triggers on the Apex Classes and Apex Triggers pages.

Cool! The code coverage calculation is pretty simple and we can cheat the system. Just use the following code


/*
Please improve your tests and remove this class as soon as possible
*/
public class CodeCoverageHack {
    public static void hack() {
        Integer i = 0;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        // you can continue this method with i++; up to 3000 lines
        // after that you would be stoped by limit of size
        // but you can create a few such methods
 }

    public static void hack1() {
         // do the same thing ...
    }

    @isTest static void runTest() {
        CodeCoverageHack.hack();
        CodeCoverageHack.hack1();
        //...
        CodeCoverageHack.hackN();
    }
}
That’s all.   ✌

How to run future method in test class


We have to use future method inside the  startTest/stopTest:

Test.startTest();
myClass.futuremethod( someID );
Test.stopTest();

Test.stopTest() does not return until your future method has completed.

Tuesday, 17 July 2018


Customize error message for trigger and display error message below the field

This Post demonstrates how to display error message in particular field level.

SObject SomeRecord;
SomeRecord.SomeField__c.addError('Custom Message');
//or
SomeRecord.someField__c.addError(someException);

Note:

We cannot add it to a field dynamically. This error mapping can only be done with a hard-coded field.


List has no rows for assignment to SObject  error

 Consider following query:
   
      id p;
      user u = [SELECT Id from user where Name = :username];
      if (u != null)
      p = u.Id;

  •  The above code will fail if there is no user record with the matching username. It doesn't actually return a null.


 It would be safer to do the following:

    id p;
     user[] userlist = [SELECT Id from user where Name = :username];
     if (userlist.size() > 0)
       p = userlist[0].Id;

Monday, 16 July 2018


Trigger for Adding and removing User to Permission set based on User roles


trigger AssignPermissionSet on User (after insert,after Update) {
    PermissionSet pereset = [SELECT Id FROM PermissionSet WHERE Label ='SBU Impact Visible'];
    Set<ID> addIds = new Set<Id>(),
            removeIds = new Set<Id>(),
            roleIds = new Map<Id, UserRole>([
        SELECT  Id FROM UserRole
        WHERE   Name LIKE '%E&C%' OR Name LIKE '%Commerical Ops%' OR Name LIKE '%Energy & Chemicals%' OR Name LIKE '%All Fluor%'
    ]).keySet();
    for(User record: Trigger.new) {
        (record.IsActive && roleIds.contains(record.UserRoleId)? addIds: removeIds).add(record.Id);
    }
   
    PermissionSetAssignment[] permissionSetList = new PermissionSetAssignment[0];
    addIds.removeAll(new Map<Id, AggregateResult>([SELECT AssigneeId Id FROM PermissionSetAssignment
       WHERE AssigneeId = :addIds AND PermissionSetId = :pereset.Id GROUP BY AssigneeId]).keySet());
   
    for(Id userId: addIds) {
        permissionSetList.add(new PermissionSetAssignment(PermissionSetId = pereset.id, AssigneeId = userId));
    }
    upsert permissionSetList;
    delete [SELECT Id FROM PermissionSetAssignment WHERE AssigneeId = :removeIds AND PermissionSetId = :pereset.Id];
}

Friday, 6 July 2018

                            PermissionSetAssignment:



  • Use the PermissionSetAssignment object to query permission set assignments to find out which permission sets are assigned to which users.
  • Each user may be assigned to many permission sets and each permission set may be assigned to many users.
  • Each PermissionSetAssignment ID represents the association of a single user and single permission set.

For example, to search for all of the permission sets assigned to a particular user:

SELECT Id, PermissionSetId
FROM PermissionSetAssignment
WHERE AssigneeId = '005600000017cKt'

To search for all users assigned to a particular permission set:

SELECT Id, AssigneeId
FROM PermissionSetAssignment
WHERE PermissionSetId = '0PS30000000000e'

Note:

You can also create a new permission set assignment, or use delete to remove a permission set that's assigned to a user. To update an assignment, delete an existing assignment and insert a new one.

Possible Errors:



Solution:

When assigning a permission set, if the PermissionSet ​ has a UserLicenseId, its UserLicenseId and the Profile ​UserLicenseId must match.


If Permission set is already present for user.Following Error will occur.




Wednesday, 23 May 2018

   DML Statement in 'after trigger' and not in 'before trigger'?


According to document, first Before trigger fire and then after trigger fire.In between of these events all the records saved to database but doesn't committed yet
  • Before insert event
  • Data committed to database
  • After insert event

Means when you use before insert operation records are not committed to database so If we change the trigger context record's value then we don't need perform DML (This is Id is not generated because it is not committed to database)

  • Once it is committed to database means the record Id is generated and your trigger records in read only mode you can't update the values now(because it is committed to database).That's why we need to perform extra DML for updating records.


Note: If in after event if any error occurs then complete DML operation rollback.

Best way if you want to update the same record in trigger then always go with before event. This way you can skip the extra DML.

Wednesday, 14 March 2018

       System.ListException: Duplicate id in list: 001XXXXXXXXXXXX

Lists can hold duplicate values, but if it contains duplicate sobject IDs and you try to update you'll get the error.

Solution:

1. Create a map of  <id,sobject>
2. Convert the list to Map so that the duplicate IDs are removed.
3. Update the values part of the Map.

Sample code :

// pick up any id from your salesforce org, in this sample it is account id.
id aid = '0017F000002WkkdQAC';

list <account> al = new list <account>();

for(account a : [select id from account where id ='0017F000002WkkdQAC']){
account acc = new account(id = aid);
    al.add(a);
    al.add(acc);
}
//create a map that will hold the values of the list
map<id,account> accmap = new map<id,account>();

//put all the values from the list to map.
accmap.putall(al);
if(accmap.size()>0){
update accmap.values();
}

Saturday, 24 February 2018

             Using JSON in Visualforce page in Salesforce




JSON stands for “Java Script Object Notation“.

JSON.serialize() is used to generate JSON. It is a lightweight data-interchange format.

JSON is built on two structures:
  • A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
  • An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
---------------------------------------------------------------------------------------------------------

<apex:page controller="sample1" action="{!parseJson}">
    <p>
       <b> displaying json format in visulaforce page</b>
    </p>
    {!text1}
 
    <apex:pageblock >
         <p>
        <b> Displaying Json data in PageBloack Table</b>
    </p>
        <apex:pageblockTable value="{!jsonList}" var="json">
            <apex:column headerValue="id" value="{!json.id}"/>
            <apex:column headerValue="name" value="{!json.name}"/>
        </apex:pageblockTable>
    </apex:pageblock>
</apex:page>


-------------------------------------------------------------------------------------


public class sample1 {
 public String text1 {get;set;}
    public list<JsonWrapper> jsonList{get;set;}
    public sample1()
    {
         jsonList=new list<JsonWrapper>();
    } 
    public void parseJson()
    {
        String soql = 'SELECT Name FROM Account LIMIT 5';
        List<Account> acct = Database.Query(soql);
        text1 = JSON.serialize(acct);
        jsonList=(List<JsonWrapper>) System.JSON.deserialize(text1,List<JsonWrapper>.class);
    }
 
 
    public class JsonWrapper{
        public string id{get;set;}
        public string name{get;set;}
    }
}

Image:


Wednesday, 17 January 2018

Create a modal or popup box in salesforce Lightning


I am going to demonstrate salesforce lightning popup model. This model is very simple here I used aura: if condition to show and hide the model.


LightningPopup.cmp

<aura:component >
    <aura:attribute name="openmodel" type="boolean" default="false"/>
    <div class="slds-m-around--xx-large">
        <button class="slds-button slds-button--brand" onclick="{!c.openModel}">Pop up Model</button>  
        <aura:if isTrue="{!v.openmodel}">
            <div role="dialog" tabindex="-1" aria-labelledby="header99" class="slds-modal slds-fade-in-open ">
                <div class="slds-modal__container">
                    <div class="slds-modal__header">
                        <button class="slds-button slds-modal__close slds-button--icon-inverse" title="Close" onclick="{!c.closeModel}">
                            X
                            <span class="slds-assistive-text">Close</span>
                        </button>
                        <h2 id="header99" class="slds-text-heading--medium">Some Inspiration never dies</h2>
                    </div>
                    
                    <div class="slds-modal__content slds-p-around--medium">
                        <p><b>Stay true to yourself, yet always be open to learn. Work hard, and never give up on your dreams, even when nobody else believes they can come true but you. These are not cliches but real tools you need no matter what you do in life to stay focused on your path.
                            
                            </b>
                        </p>
                    </div>
                    
                    <div class="slds-modal__footer">
                        <button class="slds-button slds-button--neutral" onclick="{!c.closeModel}" >Cancel</button>
                        
                    </div>
                </div>
            </div>
            <div class="slds-backdrop slds-backdrop--open"></div>
            
        </aura:if>
    </div>
</aura:component>
---------------------------------------------------------------------------------------------
LightningPopup.controller
({
    openModel: function(component, event, helper) {
        
        component.set("v.openmodel", true);
    },
    
    closeModel: function(component, event, helper) {
        
        component.set("v.openmodel", false);
    }
})
------------------------------------------------------------------------------
Preview it using salesforce Lightning App:

<aura:application extends="force:slds">
    <c:LightningPopup />
</aura:application>

Saturday, 13 January 2018

Simple SOSL scenario:

Create a visual force page:

<apex:page controller="SOSLController">
    <apex:form >
        <apex:inputText value="{!searchStr}"/>
        <apex:commandButton value="Search in Account, Contact, Opportunity" action="{!soslDemo_method}" reRender="acct,error,oppt,cont" status="actStatusId"/>
        <apex:actionStatus id="actStatusId">
            <apex:facet name="start" >
                <img src="/img/loading.gif"/>                    
            </apex:facet>
        </apex:actionStatus>
    </apex:form>
    
    <apex:outputPanel title="" id="error">
        <apex:pageMessages ></apex:pageMessages>
    </apex:outputPanel>
    
    <apex:pageBlock title="Accounts" id="acct">
        <apex:pageblockTable value="{!accList }" var="acc">
            <apex:column value="{!acc.name}"/>
            <apex:column value="{!acc.Type}"/>
        </apex:pageblockTable>
    </apex:pageBlock>
    
    <apex:pageBlock title="Contacts" id="cont">
        <apex:pageblockTable value="{!conList}" var="con">
            <apex:column value="{!con.name}"/>
            <apex:column value="{!con.email}"/>
        </apex:pageblockTable>
    </apex:pageBlock>
    
    <apex:pageBlock title="Opportunities" id="oppt">
        <apex:pageblockTable value="{!optyList}" var="opty">
            <apex:column value="{!opty.name}"/>
            <apex:column value="{!opty.StageName}"/>
        </apex:pageblockTable>
    </apex:pageBlock>
    
</apex:page>
--------------------------------------------------------------------------------------

Public with sharing class SOSLController{
    Public List<Opportunity> optyList {get;set;}
    Public List<contact> conList{get;set;}
    Public List<account> accList{get;set;}
    
    Public String searchStr{get;set;}
    Public SOSLController(){
    }
    
    Public void soslDemo_method(){
        optyList = New List<Opportunity>();
        conList = New List<contact>();
        accList = New List<account>();
        if(searchStr.length() > 1){
            String searchStr1 = '*'+searchStr+'*';
            String searchQuery = 'FIND \'' + searchStr1 + '\' IN ALL FIELDS RETURNING  Account (Id,Name,type),Contact(name,email),Opportunity(name,StageName)';
            List<List <sObject>> searchList = search.query(searchQuery);
            accList = ((List<Account>)searchList[0]);
            conList  = ((List<contact>)searchList[1]);
            optyList = ((List<Opportunity>)searchList[2]);
            if(accList.size() == 0 && conList.size() == 0 && optyList.size() == 0){
                apexPages.addmessage(new apexpages.message(apexpages.severity.Error, 'Sory, no results returned with matching string..'));
                return;
            }
        }
        else{
            apexPages.addmessage(new apexpages.message(apexpages.severity.Error, 'Please enter at least two characters..'));
            return;
        }
    }
}
--------------------------------------------------------------------------------------------




                           SOSL Queries:

  • Salesforce Object Search Language (SOSL) is a Salesforce search language that is used to perform text searches in records. 
  • Use SOSL to search fields across multiple standard and custom object records in Salesforce.

This is an example of a SOSL query that searches for accounts and contacts that have any fields with the word 'SFDC'.

List<List<SObject>> searchList = [FIND 'SFDC' IN ALL FIELDS
                                      RETURNING Account(Name), Contact(FirstName,LastName)];
 
Differences and Similarities Between SOQL and SOSL

Like SOQL, SOSL allows you to search your organization’s records for specific information. Unlike SOQL, which can only query one standard or custom object at a time, a single SOSL query can search all objects.

Another difference is that SOSL matches fields based on a word match while SOQL performs an exact match by default (when not using wildcards). For example, searching for 'Digital' in SOSL returns records whose field values are 'Digital' or 'The Digital Company', but SOQL returns only records with field values of 'Digital'.

Steps:
In the Developer Console, open the Execute Anonymous window from the Debug menu.
Insert the below snippet in the window and click Execute.

// Add account and related contact
Account acct = new Account(
    Name='SFDC Computing',
    Phone='(415)555-1212',
    NumberOfEmployees=50,
    BillingCity='San Francisco');
insert acct;

// Once the account is inserted, the sObject will be
// populated with an ID.
// Get this ID.
ID acctID = acct.ID;

// Add a contact to this account.
Contact con = new Contact(
    FirstName='Carol',
    LastName='Ruiz',
    Phone='(415)555-1212',
    Department='Wingo',
    AccountId=acctID);
insert con;

// Add account with no contact
Account acct2 = new Account(
    Name='The SFDC Query Man',
    Phone='(310)555-1213',
    NumberOfEmployees=50,
    BillingCity='Los Angeles',
    Description='Expert in wing technologies.');
insert acct2;


Let’s try running the following SOSL example:

In the Developer Console, click the Query Editor tab.
Copy and paste the following into the first box under Query Editor, and then click Execute.

FIND {Wingo} IN ALL FIELDS RETURNING Account(Name), Contact(FirstName,LastName,Department)


The search query in the Query Editor and the API must be enclosed within curly brackets ({Wingo}). In contrast, in Apex the search query is enclosed within single quotes ('Wingo').


Basic SOSL Syntax
SOSL allows you to specify the following search criteria:
Text expression (single word or a phrase) to search for
Scope of fields to search
List of objects and fields to retrieve
Conditions for selecting rows in the source objects


Execute this snippet in the Execute Anonymous window of the Developer Console. Next, inspect the debug log to verify that all records are returned.

List<List<sObject>> searchList = [FIND 'Wingo OR SFDC' IN ALL FIELDS
                   RETURNING Account(Name),Contact(FirstName,LastName,Department)];
Account[] searchAccounts = (Account[])searchList[0];
Contact[] searchContacts = (Contact[])searchList[1];

System.debug('Found the following accounts.');
for (Account a : searchAccounts) {
    System.debug(a.Name);
}

System.debug('Found the following contacts.');
for (Contact c : searchContacts) {
    System.debug(c.LastName + ', ' + c.FirstName);
}