APEX App Object Dependencies

  • Got a lot of APEX applications, and/or a schema with lots of objects?
  • Not sure exactly what database objects are used by which application?
  • Not sure dropping a particular schema object might break something in your application?
  • Not sure if all the SQL and PL/SQL in every page of your application still runs without error?

If your answer to any of the above is “Yes”, you may be interested in a new API that has been added in APEX 24.1.

Photograph of clouds lit by sunset over eucalyptus trees.

You can use this API to scan your application for any references to any schema objects, whether it refers to objects in a region, SQL queries, PL/SQL processes, and even plugins. Run this in your workspace, giving it the ID of an application you want to scan:

begin
  apex_app_object_dependency.scan(p_application_id => :app_id);
end;

This scans through the whole application by generating a small temporary procedure that tests each schema object name, SQL, or PL/SQL. As it goes, it checks that the code compiles without error, and if it compiles, it saves a list of dependencies detected by the database including tables, views, stored functions and procedures, packages, and synonyms. It drops the temporary procedure at the end.

Depending on how big your application is, the scan may take some time to complete (e.g. 30 to 60 seconds) due to the time required to compile and analyze each temporary procedure. If you find it gets stopped prematurely due to a timeout error, you can run it in the background (for example, I like to use an “Execution Chain” process in an APEX application with “Run in Background” enabled).

Note that none of your application code is actually executed, so there should be no side effects of running the scan. However, if your database has any DDL triggers, they may fire as the temporary procedure is created and dropped.

Viewing the Scan Results

Once the scan is complete, you can query the results at your leisure by querying these views:

  • APEX_USED_DB_OBJECTS
  • APEX_USED_DB_OBJECT_COMP_PROPS
  • APEX_USED_DB_OBJ_DEPENDENCIES

APEX_USED_DB_OBJECTS

This lists each schema object that is used at least once in your application.

select
    referenced_type, referenced_owner,
    referenced_name, referenced_sub_name,
    usage_count
from apex_used_db_objects
where application_id = :app_id;
Table of REFERENCED_TYPE, REFERENCED_OWNER, REFERENCED_NAME, REFERENCED_SUB_NAME, and USAGE_COUNT.
Results include Columns, a Method, a Package, a Schema, and some Synonyms.

Note that “USAGE_COUNT” is the number of distinct component properties that refer to the schema object; if a single component (e.g. a Process) refers to an object multiple times, it will only count as one usage.

If your database package is compiled with PL/Scope enabled, the dependency analysis will also report fine-grained dependencies on the functions, procedures, and other components within the database package.

APEX_USED_DB_OBJECT_COMP_PROPS

This lists each component property in your application that references at least one schema object.

select
    page_id,
    component_type_name, component_display_name,
    property_group_name, property_name
from apex_used_db_object_comp_props
where application_id = :app_id;
Table of PAGE_ID, COMPONENT_TYPE_NAME, COMPONENT_DISPLAY_NAME, PROPERTY_GROUP_NAME, PROPERTY_NAME.
Results include various pages in an application with Regions, Processes, and a Series.

You can also include the column CODE_FRAGMENT to show the object name, SQL or PL/SQL that was analyzed.

If a component property cannot be analyzed due to a compile error (e.g. if an expected database object is missing) the same view will tell you what the compile error was, which may help you to determine what’s gone wrong.

select
    page_id,
    component_type_name, component_display_name,
    property_group_name, property_name,
    code_fragment, error_message
from apex_used_db_object_comp_props
where application_id = :app_id
and error_message is not null;

APEX_USED_DB_OBJ_DEPENDENCIES

This is the complete report showing for each component property, all the database objects it refers to.

select
    page_id,
    component_type_name, component_display_name,
    property_group_name, property_name,
    code_fragment,
    referenced_type, referenced_owner,
    referenced_name, referenced_sub_name
from apex_used_db_obj_dependencies
where application_id = :app_id;
Table of PAGE_ID, COMPONENT_TYPE_NAME, COMPONENT_DISPLAY_NAME, CODE_FRAGMENT, REFERENCED_TYPE, REFERENCED_OWNER, REFERENCED_NAME, REFERENCED_SUB_NAME.
Results include some Regions, an Item, some Validations, and a Process.
Results indicate dependencies on database Tables, a Synonym, some Packages, and a Method.
(some columns were removed from this screenshot)

Using the API

The results of a scan will be retained until the application is re-scanned. You can scan any number of applications in your workspace and analyze the results all together if you need. If an application is modified, you can re-scan it to refresh the report.

You may find it useful, so I encourage you to give it a try. If you do, please note a few caveats:

  • The documentation for this API is not yet available, but is being worked on.
  • When APEX is upgraded to a new version, all report results are wiped. You can then re-scan your applications to get up-to-date results.
  • The reports do not include recursive dependencies – e.g. if your application refers to a view, the report will not list the underlying tables of the view.
  • If the application includes any plugins, the dependencies report will include references to some internal plugin-related APIs even if your code doesn’t directly reference them.
  • If your application executes any dynamic SQL or PL/SQL (e.g. using “execute immediate”), any dependencies arising from the dynamic code will not be reported.
  • There are some component properties that are not included in the scan, such as the column names in a report (however, the data source for the region is scanned).

In spite of the caveats, I’m sure there are quite a few ways this new API will prove useful. We expect it will be further improved in future releases, including being integrated into the APEX Application Builder.