Your function_private only declared in the package body, so its scope is limited only by other procedures in your package. Therefore, it will have to correspond to the purity level of these calling procedures, otherwise the compiler will throw an exception.
Compare this safe declaration (note I expanded the purity of function_public ) ...
SQL> CREATE OR REPLACE PACKAGE PRAGMA_TEST AS 2 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2; 3 PRAGMA RESTRICT_REFERENCES( function_public, WNDS, WNPS, RNDS); 4 END PRAGMA_TEST; 5 / Package created. SQL> CREATE OR REPLACE PACKAGE BODY PRAGMA_TEST AS 2 FUNCTION function_private(y IN VARCHAR2) RETURN VARCHAR2 IS 3 BEGIN 4 return 'no harm done'; 5 END; 6 7 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2 IS 8 BEGIN 9 return function_private(x); 10 END; 11 END PRAGMA_TEST; 12 / Package body created. SQL>
... with this unsafe ...
SQL> CREATE OR REPLACE PACKAGE BODY PRAGMA_TEST AS 2 FUNCTION function_private(y IN VARCHAR2) RETURN VARCHAR2 IS 3 rv varchar2(1); 4 BEGIN 5 select dummy into rv from dual; 6 return rv; 7 END; 8 9 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2 IS 10 BEGIN 11 return function_private(x); 12 END; 13 END PRAGMA_TEST; 14 / Warning: Package Body created with compilation errors. SQL> sho err Errors for PACKAGE BODY PRAGMA_TEST: LINE/COL ERROR -------- ----------------------------------------------------------------- 9/3 PLS-00452: Subprogram 'FUNCTION_PUBLIC' violates its associated pragma SQL>
The point of the RESTRICTS_REFERENCES pragma is that the procedures declared in the package specification can be used by other packages, even SQL statements, owned or executed by other users (schemas), which may not have access to our source code of the package body. Pragma is the method by which we offer them assurances regarding the impact of including our code in them. This is why a pragma must be declared in the specification because it is the only piece of code that opens when we provide EXECUTE in the package to another user.
change
And now, after seeing your revised code example, I understand what you are trying to do. It is not, it will not, it cannot work. We are allowed to use only batch functions that were declared in spec = public functions - in SQL. It doesn't matter if SQL is written in SQL * Plus or encoded in another packed procedure. The reason why it is clear enough in the error stack:
SQL> CREATE OR REPLACE PACKAGE PRAGMA_TEST AS 2 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2; 3 PRAGMA RESTRICT_REFERENCES( function_public, WNDS, WNPS); 4 END PRAGMA_TEST; 5 / Package created. SQL> CREATE OR REPLACE PACKAGE BODY PRAGMA_TEST AS 2 FUNCTION function_private(y IN VARCHAR2) RETURN VARCHAR2 IS 3 rv varchar2(1); 4 BEGIN 5 select dummy into rv from dual; 6 return rv; 7 END; 8 9 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2 IS 10 rv varchar2(1); 11 BEGIN 12 select function_private(x) into rv from dual; 13 return rv; 14 END; 15 END PRAGMA_TEST; 16 / Warning: Package Body created with compilation errors. SQL> sho err Errors for PACKAGE BODY PRAGMA_TEST: LINE/COL ERROR -------- ----------------------------------------------------------------- 12/6 PL/SQL: SQL Statement ignored 12/13 PL/SQL: ORA-00904: : invalid identifier 12/13 PLS-00231: function 'FUNCTION_PRIVATE' may not be used in SQL SQL>
The compiler assigns ORA-00904: invalid identifier because the function is not declared in spec; it has nothing to do with purity levels,
area note
PL / SQL does not consist entirely of the rules for defining it : we can use private variables in our packed SQL statement:
SQL> CREATE OR REPLACE PACKAGE BODY PRAGMA_TEST AS 2 3 gv constant varchar2(8) := 'global'; 4 5 FUNCTION function_private(y IN VARCHAR2) RETURN VARCHAR2 IS 6 rv varchar2(1); 7 BEGIN 8 select dummy into rv from dual; 9 return rv; 10 END; 11 12 FUNCTION function_public(x IN VARCHAR2) RETURN VARCHAR2 IS 13 rv varchar2(10); 14 BEGIN 15 select gv||'+'||dummy into rv from dual; 16 return rv; 17 END; 18 END PRAGMA_TEST; 19 / Package body created. SQL>
These are simply functions and types that wm must declare in the specification if we want to use them in SQL statements.