+ Start a Discussion

perl and queryMore

I've been having some trouble wrapping my head around this one. Hope someone can help. I'd really appreciate the help.

I want to reliably iterate ove the responses from my queries. Not sure how I'd do that when the URL for the results are different for query (//queryResponse/result/records') and querymore (//queryMoreResponse/result/records').

Can someone help me out with some sample code? I've been trying to translate the c++ code provided in the API doc to perl without any luck. This one doesnt work.

$r = $sf->query('query' => "select Id from Case" );
$numrecords = $r->valueof('//queryResponse/result')->{size};
my $done = "false";
if ( $numrecords > 0 ) {
        while ( uc($done) eq "FALSE" ) {
                foreach $elem ( $r->valueof('//queryResponse/result/records') ) {
                        print $elem->{Id}[0]."\n";
                $done = $r->valueof('//queryResponse/result')->{done};
                if ( uc($done) eq "FALSE" ) {
                        $r = $sf->queryMore( 'queryLocator' => $r->valueof('//queryResponse/result')->{queryLocator} );
                        $numrecords = $r->valueof('//queryMoreResponse/result')->{size};
                        foreach $elem ( $r->valueof('//queryMoreResponse/result/records') ) {
                                print $elem->{Id}[0]."\n";
                } else {
                        $done = $r->valueof('//queryResponse/result')->{done};
} else {
        print "No records match criteria\n";

Message Edited by sk2006 on 05-23-2006 06:04 AM


how about ...?

1. Get out quickly if the first query returned nothing

if ($numrecords == 0) {

  print "No records match criteria\n";


2. Next, do the processing of 'query' results outside the while loop.

3. Then loop over calling and processing querymore (while $done is 'false').

Ron HessRon Hess
here is my query() and queryMore() loop, actualy calls a function with an array of records if you want to process them as they are fetched, however if not, it returns a full list of records.

note, it does not use size, rather looks at "//done"

sub qlist { my $_sf = shift; my $soql = shift;  my $subref = shift;
 print "qlist ( $soql ) \n" if $debug > 2;
 my $q = $_sf->query( query =>$soql, limit => $lim );
 my @trans = $q->valueof('//records'); 
 $subref and $subref->(@trans); 
 while ( 'false' eq $q->valueof('//done') ) { # query more
  $q = $_sf->queryMore( queryLocator => $q->valueof('//queryLocator'), limit => $lim ); 
  my @more = $q->valueof('//records');
  $subref and $subref->(@more); 
  push @trans, @more;
 print "qlist $soql \n\treturns records:",$#trans+1,"\n" if $debug > 2;
 return @trans;


By the way, if you need to do a lot of processing, your queryLocator can expire before you make the next queryMore call.  Just something to watch out for.  Drove me nuts for a while.
Check out WWW::Salesforce and WWW::Salesforce::Simple on CPAN.  http://search.cpan.org/

You will find an example on how to use queryMore in WWW::Salesforce::Simple.

Let me know if you have any questions.


This might be useful to anyone battling the odds using Perl - here is an example of query, querymore and relationship queries .


sub SalesforceQuery{
    my $query = "select Id, Email,FirstName, LastName, UserName,ContactID, Contact.Id" .
        " ,Contact.Name, Contact.AccountId,Contact.Account.Name, isActive ".
        " from User u where isActive = true and Contactid <> ''";    
my $result = $sforce->query(('query' => $query),('limit' => '1000'));
my $fetchsize = $result->valueof('//queryResponse/result')->{size};

my @trans = $result->valueof('//records');
print "trans is ".scalar (@trans)."\n";
my $count = scalar (@trans);

while ('false' eq $result->valueof('//done')&& $count < $fetchsize) {
      $result = $sforce->queryMore(queryLocator => $result->valueof('//queryLocator'), limit => '1000');
      my @more = $result->valueof('//records');
      push @trans, @more ;
      # print "trans is ".scalar (@trans)."\n";

$count += scalar (@more);
print "there are $count records retrieved \n ";

print $result->valueof('//done')."\n";

$count = 0;

#open a file
$file = 'User.csv';
open (INFO,">$file");

foreach my $row (@trans) {
    $_ = $row->{'Id'};
    my @idArray = map{$_}(@{$row->{'Id'}});
    print INFO $idArray[0],",".$count++.",".$row->{'Email'}.",".$row->{'ContactId'}.",".$row->{'FirstName'}.",".$row->{'Contact'}->{'Id'}[0].",".$row->{'Contact'}->{'Name'}.",".$row->{'Contact'}->{'AccountId'}.",".$row->{'Contact'}->{'Account'}->{'Name'}."\n";
    print $count."\n";
print "end";