When you are calling Database.delete it is returning a List of Database.DeleteResult records if you are doing it to a list.
There are several things that could cause only 1 record to be returned here.
1) If you are calling Database.delete inside a query on each individual record, you will only get 1 error returned.
for (Account acc: scope)
Database.DeleteResult result = Database.delete(acc);
//This is only asking for all of the errors on a single record here
List<Database.Error> errors = result.getErrors();
2) You are looking at a single result instead of all of the results.
List<Database.DeleteResult> results = Database.delete(scope);
for (Database.DeleteResult result: results)
//Again, this is only for a single record
Database.Error errors = result.getErrors();
It's harder to tell for sure what is going on though unless you show us what you have done.
In order to investigate this further I created a new dev org on which to play, installed my package, created a specialist implementation of my AdaptiveBatch API and tried out various types of processing.
I stumbled upon the answer to the issue because I started receiving Developer Script Exception emails - I was not the recipient of these on the sandbox where we first saw this problem.
The logs confirm that the start and finish method async executions for the batch were being triggered and processed fine. The processing was failing with the strange internal error only during the initialization of the execute method async execution.
The start method returns a query locator (SOQL). Where this references one of our package's custom fields the namespace prefix was not specified. The processing seems to handle this fine, as it always has historically across our code base, with log entries like:
08:17:01.0 (183716704)|SOQL_EXECUTE_BEGIN||Aggregations:0|SELECT firstname, lastname, payment_account__c, id FROM Contact
You can see from this that (in my test org) there are two rows selected, and these include the "payment_account__c" field being queried. That field is actually from our package, but is named without the prefix.
However, when execute is to be invoked the log simply contains something like:
08:17:01.0 (36070965)|FATAL_ERROR|Internal Salesforce.com Error
This then appears to relate to the developer script exception email:
Developer script exception from XXX:
SELECT firstname, lastname, payment_account__c, id FROM Contact
^ ERROR at Row:1:Column:29 No such column 'payment_account__c' on entity 'Contact'.
If you are attempting to use a custom field, be sure to append the '__c' after
the custom field name. Please reference your WSDL or the describe call for the
It seems that this is not, therefore, due to the Batchable methods being public (rather than global), which is a really good thing. At least I can address this behind the API by making sure namespaces are applied explicitly in the SOQL query fields.
Strange that it trips up in this specific context and not otherwise. I mean - our other batches fully implemented in the package don't require the namespace prefix, but this batch who's execute method is fully implemented in the package but where the actual queued class is outside the package fails, yet only in execute and not in start. This inconsistent start/execute behaviour is very strange and the fact it is reported as an internal error with no useful log detail doesn't help.
1)Yes, a batch can be called from another batch. When you implement Batchable interface in a class, you implement three methods, start, execute and finish. You can call another batch from a batch by calling another batch in finish method of one batch. This way also saves you from the limit around number of batch jobs which will be running simultaneously for your org, since second batch will run after first batch has completed running.
3)Batch processing is asynchronous. These will be run when salesforce has avaialble resources.
4) Triggers run when DML operations are performed by user / apex data loader / external system. These should be synchronous in nature. Although we can call asynchronous methods(@future) from a trigger. So we can do both synchronous and async processing in triggers.
6) Roles can be moved using change sets. It is better to create Profiles manually again.