Nada a ver com a declaração para a frente em tudo.
Isso lida com o fato de que você está usando uma consulta SQL para chamar a função . Parece que ao usar uma instrução para invocar uma função, você não está mais dentro do escopo do pacote PL/SQL, portanto, você só pode chamar funções disponíveis publicamente.
Quanto ao porquê , eu só posso adivinhar, então não tome isso como certo, mas PL/SQL e SQL têm mecanismos diferentes . Então, ao fazer uma consulta sql, mesmo dentro do seu pacote pl/sql, você vai para o nível do SQL onde ele vai checar novamente as permissões de acordo com o mecanismo SQL. Portanto, ele não tem ideia de que é executado de dentro de um pacote PL/SQL e você deve ter permissão para chamar a função privada.
Acho que a diferença de engines pode ser verificada facilmente, tente usar um varchar2 de 32000, vai funcionar dentro da sua função pl/sql. Agora, se você chamar sua função pl/sql retornando um
varchar2(32000)
, ele falhará. Este é um problema que encontrei, mas não tenho nenhum banco de dados para fornecer um trecho.