Retreive a list of private procedures/functions from a package body - oracle

I want to obtain a list with all private procedures/functions from a package body.
For public object it is easy but I have no idea how to do that for private objects.

The nature of private functions is that they are private. There are no data dictionary views which expose them by default. USER_PROCEDURES and USER_ARGUMENTS only show information for public procedures (the ones defined in a package spec0.
However, we can get information about them using PL/SCOPE, but doing so requires a little bit of additional effort:
SQL> alter session set plscope_settings='IDENTIFIERS:ALL';
SQL> alter package your_package compile body;
Now you can find your private program units with this query:
select ui.type, ui.name, ui.usage_id
from user_identifiers ui
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DEFINITION'
and ui.type in ('PROCEDURE', 'FUNCTION')
minus
( select 'PROCEDURE', upr.procedure_name
from user_procedures upr
where upr.object_name = 'YOUR_PACKAGE'
union
select 'FUNCTION', uarg.object_name
from user_arguments uarg
where uarg.package_name = 'YOUR_PACKAGE'
and uarg.position = 0
);
To get the arguments of a private procedure plug the USAGE_ID from the previous query into this query:
select ui.name
, ui.type
, ui.usage_id
, ui2.type as param_datatype
from user_identifiers ui
left join user_identifiers ui2
on ui2.usage_context_id = ui.usage_id
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DECLARATION'
and ui.usage_context_id = :private_proc_usage_id
/
This needs to be a left join because user_identifiers has datatype entries for scalar datatypes (character, number, date, clob) but not complex datatypes (xmltype, user-defined types).
We can get lots of information about procedures from PL/SCOPE, even though it is not as easy as querying USER_PROCEDURES or USER_ARGUMENTS (in fact, it is surprisingly clunky). Find out more. Be aware that PL/SCOPE data is stored on the SYSAUX tablespace, so don't get into hot water with your DBA!

Related

Retrieve argument details defined in private function/procedure [duplicate]

I want to obtain a list with all private procedures/functions from a package body.
For public object it is easy but I have no idea how to do that for private objects.
The nature of private functions is that they are private. There are no data dictionary views which expose them by default. USER_PROCEDURES and USER_ARGUMENTS only show information for public procedures (the ones defined in a package spec0.
However, we can get information about them using PL/SCOPE, but doing so requires a little bit of additional effort:
SQL> alter session set plscope_settings='IDENTIFIERS:ALL';
SQL> alter package your_package compile body;
Now you can find your private program units with this query:
select ui.type, ui.name, ui.usage_id
from user_identifiers ui
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DEFINITION'
and ui.type in ('PROCEDURE', 'FUNCTION')
minus
( select 'PROCEDURE', upr.procedure_name
from user_procedures upr
where upr.object_name = 'YOUR_PACKAGE'
union
select 'FUNCTION', uarg.object_name
from user_arguments uarg
where uarg.package_name = 'YOUR_PACKAGE'
and uarg.position = 0
);
To get the arguments of a private procedure plug the USAGE_ID from the previous query into this query:
select ui.name
, ui.type
, ui.usage_id
, ui2.type as param_datatype
from user_identifiers ui
left join user_identifiers ui2
on ui2.usage_context_id = ui.usage_id
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DECLARATION'
and ui.usage_context_id = :private_proc_usage_id
/
This needs to be a left join because user_identifiers has datatype entries for scalar datatypes (character, number, date, clob) but not complex datatypes (xmltype, user-defined types).
We can get lots of information about procedures from PL/SCOPE, even though it is not as easy as querying USER_PROCEDURES or USER_ARGUMENTS (in fact, it is surprisingly clunky). Find out more. Be aware that PL/SCOPE data is stored on the SYSAUX tablespace, so don't get into hot water with your DBA!

To extract private arguments details from procedure and function in Oracle [duplicate]

I want to obtain a list with all private procedures/functions from a package body.
For public object it is easy but I have no idea how to do that for private objects.
The nature of private functions is that they are private. There are no data dictionary views which expose them by default. USER_PROCEDURES and USER_ARGUMENTS only show information for public procedures (the ones defined in a package spec0.
However, we can get information about them using PL/SCOPE, but doing so requires a little bit of additional effort:
SQL> alter session set plscope_settings='IDENTIFIERS:ALL';
SQL> alter package your_package compile body;
Now you can find your private program units with this query:
select ui.type, ui.name, ui.usage_id
from user_identifiers ui
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DEFINITION'
and ui.type in ('PROCEDURE', 'FUNCTION')
minus
( select 'PROCEDURE', upr.procedure_name
from user_procedures upr
where upr.object_name = 'YOUR_PACKAGE'
union
select 'FUNCTION', uarg.object_name
from user_arguments uarg
where uarg.package_name = 'YOUR_PACKAGE'
and uarg.position = 0
);
To get the arguments of a private procedure plug the USAGE_ID from the previous query into this query:
select ui.name
, ui.type
, ui.usage_id
, ui2.type as param_datatype
from user_identifiers ui
left join user_identifiers ui2
on ui2.usage_context_id = ui.usage_id
where ui.object_name = 'YOUR_PACKAGE'
and ui.usage = 'DECLARATION'
and ui.usage_context_id = :private_proc_usage_id
/
This needs to be a left join because user_identifiers has datatype entries for scalar datatypes (character, number, date, clob) but not complex datatypes (xmltype, user-defined types).
We can get lots of information about procedures from PL/SCOPE, even though it is not as easy as querying USER_PROCEDURES or USER_ARGUMENTS (in fact, it is surprisingly clunky). Find out more. Be aware that PL/SCOPE data is stored on the SYSAUX tablespace, so don't get into hot water with your DBA!

Record type reflection / populating a record variable of an unknown type (PL/SQL)

I have a package with a record type and a variable of that type in it:
CREATE PACKAGE my_package AS
TYPE t_rec IS RECORD(
id NUMBER,
name VARCHAR2(100),
last_updated DATE
);
v_var t_rec;
END;
I want to create an universal procedure for populating any record variable, so it can be called like this:
BEGIN
populate_record('my_package.v_var', 'MY_TABLE', CHARTOROWID(:VAR1));
END;
The logic of that procedure may look like this:
PROCEDURE populate_record(
p_var_name IN VARCHAR2,
p_table_name IN VARCHAR2,
p_rowid IN ROWID
) IS
BEGIN
-- determining a type of a given record variable
-- determining names and data types of given record variable's columns
-- selecting a row from a given table by a given rowid
-- filling out a given record variable by mapping table columns
-- to record columns by their names (using dynamic PL/SQL)
END;
But I have no idea how to obtain information about a given record. Are there any data dictionary views or built-in functions for querying record type columns?
Thanks.
P.S.: 11.2
UPDATED
I found a way to obtain info about records using PL/Scope:
CREATE OR REPLACE VIEW user_record_types AS
SELECT
i.object_name package_name,
i.name type_name
FROM
user_identifiers i
WHERE
i.object_type = 'PACKAGE'
AND i.type = 'RECORD'
AND i.usage = 'DECLARATION'
/
CREATE OR REPLACE VIEW user_record_types_columns AS
SELECT
i1.object_name package_name,
i1.name type_name,
ROW_NUMBER() OVER (
PARTITION BY
i1.object_name,
i1.name
ORDER BY
i2.usage_id
) column_num,
i2.name column_name,
i3.name column_type,
i3.type column_type_class
FROM
user_identifiers i1,
user_identifiers i2,
user_identifiers i3
WHERE
i1.object_type = 'PACKAGE'
AND i1.type = 'RECORD'
AND i1.usage = 'DECLARATION'
AND i2.object_name = i1.object_name
AND i2.object_type = i1.object_type
AND i2.type = 'VARIABLE'
AND i2.usage = 'DECLARATION'
AND i2.usage_context_id = i1.usage_id
AND i3.object_name = i2.object_name
AND i3.object_type = i2.object_type
AND i3.usage = 'REFERENCE'
AND i3.usage_context_id = i2.usage_id
/
CREATE OR REPLACE VIEW user_record_variables AS
SELECT
i1.object_name package_name,
i1.name variable_name,
CASE i2.type
WHEN 'RECORD' THEN
i2.object_name
WHEN 'PACKAGE' THEN
i2.name
END type_package_name,
CASE i2.type
WHEN 'RECORD' THEN
i2.name
WHEN 'PACKAGE' THEN
i3.name
END type_name
FROM
user_identifiers i1,
user_identifiers i2,
user_identifiers i3
WHERE
i1.object_type = 'PACKAGE'
AND i1.type = 'VARIABLE'
AND i1.usage = 'DECLARATION'
AND i2.object_name = i1.object_name
AND i2.object_type = i1.object_type
AND i2.type IN ('RECORD', 'PACKAGE')
AND i2.usage = 'REFERENCE'
AND i2.usage_context_id = i1.usage_id
AND i3.object_name (+) = i2.object_name
AND i3.object_type (+) = i2.object_type
AND i3.type (+) = 'RECORD'
AND i3.usage (+) = 'REFERENCE'
AND i3.usage_context_id (+) = i2.usage_id
/
But there is a problem when I use %ROWTYPEs, because there is no info about "what of" that %ROWTYPE is. So I think that PL/Scope is not a complete solution...
You can try to use table user_identifiers or all_identifiers if you have the access, as this other SO post shows.
You may need to recompile your packages:
alter package my_types compile plscope_settings='IDENTIFIERS:ALL' reuse settings;
Unfortunately this is only available from 11gR1.

How do I differentiate between Procedures and Functions in Oracle's Metadata?

I want to list all the Stored Procedures which use overloading in a given schema. All the procedures are within packages. I can use the SQL below to nearly get there (anything with proc_count > 1).
select
object_name, procedure_name, count(procedure_name) as proc_count
from
all_procedures
where
owner = 'SCHEMA_NAME'
group by
object_name, procedure_name
order by proc_count desc
However there seems to be no way to differentiate between a function named 'ask_version' and a procedure named 'ask_version' which I need to do in my case. The case being that our middleware has trouble calling procs where overloading is used. I need to do an impact analysis on how many places this occurs. We never call functions directly, hence the need to isolate them
Is there something that I'm missing?
all_arguments seems to help. For a function, there is an argument with position=0 (which is the return value), for procedures this argument does not exist.
SELECT object_name, procedure_name, t, COUNT(1) AS proc_count
FROM
(
SELECT p.object_name, p.procedure_name,
CASE WHEN a.object_id IS NULL THEN 'PROCEDURE' ELSE 'FUNCTION' END AS t
FROM all_procedures p
LEFT JOIN all_arguments a ON ( a.object_id = p.object_id
AND a.subprogram_id = p.subprogram_id AND a.position = 0 )
WHERE p.owner = 'SCHEMA_NAME'
)
GROUP BY object_name, procedure_name, t
ORDER BY proc_count DESC;
This is a bit tricky since Oracle stores packages as discrete objects from standalone functions and procedures.
The only easy way you can tell this is by looking at the argument metadata in ALL_ARGUMENTS. Functions have an argument at position 0 to specify the return type, whereas procedures do not.
Also, it's easy to tell if a function or procedure has overloads by checking the OVERLOAD field.
select P.OBJECT_NAME
, P.PROCEDURE_NAME
, DECODE(min(a.POSITION), 0, 'Function', 'Procedure') FUNC_OR_PROC
, DECODE(NVL(min(P.OVERLOAD), 0), 0, 'No', 'Yes') OVERLOADED
from ALL_PROCEDURES P
, ALL_ARGUMENTS a
where P.OWNER = 'FLOWS_030000'
and P.OBJECT_NAME = a.PACKAGE_NAME
and P.PROCEDURE_NAME = a.OBJECT_NAME
group by P.OBJECT_NAME, P.PROCEDURE_NAME
order by 1,2;

Native method to pull out metadata about packages, procedures and functions?

I wish to be able to query Oracle for a list of public procedures and functions that belong to a package, something along the lines of:
select procedure_name from all_package_procedures where package_name = :my_package_name;
I also wish to be able to query Oracle for a list of parameters for a given procedure or function, something along the lines of:
select parameter_name, in_or_out, parameter_type from all_function_parameters where function_name = :my_function_name;
Is this possible natively? If not, does anyone know of existing code to achieve this?
You can query USER_OBJECTS & USER_PROCEDURES to get a list of all procedures & functions belonging to a particular package
SELECT procedure_name
FROM user_procedures
WHERE object_id = (SELECT object_id
FROM user_objects
WHERE object_name = '<YOUR-PACKAGE-NAME>'
AND object_type = 'PACKAGE')
Replace user_objects & user_procedures with all_objects & all_procedures respectively to fetch packages & procedures owned by other users.
I also wish to be able to query Oracle for a list of parameters for a given procedure or function,
For this, you can query user_arguments or all_arguments to fetch parameters of on object owned by the current user & all users respectively
SELECT argument_name,
data_type
FROM user_arguments
WHERE package_name = '<name-of-your-package-procedure-function>'
My own answer, derived from Sathyas, for the reference of others. Here is a single query to pull out a denormalized result of all procedures and their arguments for a given package:
select p.procedure_name
, a.argument_name
, a.data_type
, a.defaulted
, a.default_value
, a.in_out
, a.position
from all_procedures p
inner join all_objects o
on o.object_id = p.object_id
inner join all_arguments a
on a.package_name = o.object_name
and a.object_name = p.procedure_name
where o.object_type = 'PACKAGE'
and o.object_name = 'PACKAGE_NAME'
order by p.procedure_name, a.position;

Resources