Os localizadores de consulta são gerados pelo sistema em certos casos e, se forem usados depois de expirados ou liberados, isso pode causar integrações de API ou erros de lançamento de código Apex.
Visão geral dos localizadores de consulta
Um localizador de consulta representa um cursor do lado do servidor para uma consulta. Normalmente, um localizador de consulta é retornado quando nem todos os registros solicitados em uma consulta se encaixam no conjunto de dados retornado. Dessa forma, um queryMore() pode ser emitido com o localizador de consulta fornecido para obter linhas adicionais. Por exemplo, considere uma chamada de API de consulta em que o tamanho do lote é definido como 2.000 e a organização tem mais de 2.000 contas. Nesse cenário, a conta SELECT id FROM retornará 2.000 registros e um localizador de consulta para recuperar os registros restantes.
Resolução
Número máximo de localizadores de consulta por usuário e 'INVALID_QUERY_LOCATOR' retornados em uma chamada de consulta de API. Cada usuário do Salesforce pode ter até 10 cursores de consulta abertos por vez. Este é um limite embutido em código que não pode ser aumentado. Se 10 cursores do localizador de consulta forem abertos quando um aplicativo cliente tentar abrir um novo, o cursor mais antigo será liberado. Se uma chamada for tentada para um cursor expirado ou liberado, a plataforma retornará o erro 'INVALID_QUERY_LOCATOR'. Para evitar esse erro, certifique-se de que o código do cliente não esteja mantendo abertos mais de 10 cursores do localizador de consulta. Se vários processos estiverem sendo executados usando o mesmo usuário, certifique-se de que a contagem combinada de cursores do localizador de consulta permaneça em 10 ou menos.
'INVALID_QUERY_LOCATOR' em acionadores do Apex ou controladores do Apex
Além disso, em acionadores do Apex ou controladores do Apex, essa mensagem de erro pode ser lançada em diferentes cenários, mas geralmente é causada pelo uso de consultas com consultas internas. Nesse caso, o sistema pode gerar de forma transparente para o usuário um localizador de consulta para que, se o código Apex tentar recuperar os registros filho selecionados pela consulta interna, um queryMore() seja usado para recuperá-los. Como exemplo, considere a seguinte consulta:
List<Account> accountsAndCases= [SELECT id, nome, (SELECT id, assunto, descrição FROM Cases) FROM Account];
// Os casos podem ser recuperados da seguinte forma:
List<Case> casesToUpdate = new List<Case>();
for(Account a: accountsAndCases) { // queryMore() é usado para recuperar casos filhos
casesToUpdate.addAll(a.Cases);
}
Se os casos filhos não forem recuperados imediatamente, 'consumindo' os localizadores de consulta gerados, esses localizadores de consulta podem:
- Expira após 15 minutos, ou seja liberado, pois novos localizadores de consulta podem precisar ser criados dependendo do caminho do código personalizado. Isso pode ocorrer se consultas adicionais forem inseridas entre o ponto em que os localizadores de consulta são gerados e o ponto em que são consumidos.
Observação: para evitar problemas com localizadores de consulta, você deve sempre recuperar os registros filho dentro do mesmo escopo em que foram gerados. Como regra geral, evite abordagens como as seguintes:
List<Account> accounts = Utilities.getAccountsAndCases();
List<Opportunity> oportunidades = Utilities.getOpportunities(accounts);
Utilities.updateCases(contas);
Como o sistema pode precisar criar localizadores de consulta no escopo do método Utilities.getAccountsAndCases(), pode ser necessário criar localizadores de consulta adicionais no escopo de Utilities.getOpportunities() e quando os registros da conta filho forem recuperados na linha 3 , os localizadores de consulta gerados no primeiro método podem não ser mais válidos. Em vez disso, use a seguinte abordagem:
List<Account> accounts = Utilities.getAccountsAndUpdateCases();
List<Opportunity> oportunidades = Utilities.getOpportunities(accounts);
'INVALID_QUERY_LOCATOR' no Apex em lote