Query icon
OutputValues icon
Log icon
If icon
SlackIncomingWebhook icon
Loop icon
Fail icon
Schedule icon

Oracle Invalid Object Recompile Guard

Find Oracle objects left INVALID after a dependency change, recompile them with ALTER COMPILE behind a dry-run gate, then re-read dba_objects to confirm.

Categories
DataInfrastructure

Oracle marks a schema object INVALID when something it depends on changes. Alter a table, replace a view, change a type. Every view, package, procedure, function or trigger built on top of it is flagged INVALID in dba_objects. Oracle recompiles an invalid object on first use, but that first use can be a user request that pays the compile cost or hits a genuine break hidden since the DDL ran.

This blueprint finds those objects before a user does. It reads dba_objects for the schemas you name, recompiles each flagged object with ALTER ... COMPILE, then reads dba_objects again and fails the run if anything is still INVALID.

This blueprint was created by zkasuran.

Findings

Object type in dba_objects Statement used to recompile
VIEW, PROCEDURE, FUNCTION, TRIGGER, PACKAGE, TYPE, MATERIALIZED VIEW ALTER <type> "owner"."name" COMPILE
PACKAGE BODY ALTER PACKAGE "owner"."name" COMPILE BODY
TYPE BODY ALTER TYPE "owner"."name" COMPILE BODY

Recompile runs in two passes. A package body can stay invalid on the first pass only because its spec compiled later in the same pass, so a second pass over the same set clears anything whose failure was ordering. An object still invalid after both passes has a real break, usually a column or dependency that was dropped or renamed. The run fails so a human looks at it.

How it works

  1. audit (io.kestra.plugin.jdbc.oracle.Query, read-only) reads dba_objects for the owners in object_owners where status is INVALID, limited to recompilable object types. It returns the exact ALTER ... COMPILE for each.
  2. fixes (io.kestra.plugin.core.output.OutputValues) deduplicates those statements. summary logs the invalid objects.
  3. route (io.kestra.plugin.core.flow.If):
    • clean: nothing INVALID, so it logs and stops.
    • findings: alert posts the list to Slack.
      • remediate_gate runs only when auto_remediate is true and dry_run is false.
      • remediate and remediate_second (io.kestra.plugin.core.flow.Loop, concurrencyLimit: 1) run each ALTER ... COMPILE in turn, twice. Serial on purpose, so interdependent objects do not compile against each other at once.
      • reaudit reads dba_objects again. verify_result fails the run through remediation_failed if any object is still INVALID, otherwise remediated logs the count returned to VALID.
  4. errors posts to Slack if the flow fails for any reason, including an object that could not be recompiled.

What you get

  • A scheduled check that catches invalid objects after a release instead of a user hitting one.
  • A recompile that is safe to re-run. Recompiling a valid object is a no-op.
  • A real verification step. The run passes only when dba_objects reports every object VALID.
  • Slack alerts on the findings and on any failure.

Who it's for

  • DBAs who run DDL during a release and want the dependent objects validated before traffic.
  • Platform teams that recompile schemas after a patch or an import.
  • Teams evaluating the Oracle plugin who want an example that reads the data dictionary then changes state behind a gate.

Why orchestrate this with Kestra

The usual recompile is a one-off script a DBA keeps in a drawer. Kestra runs it on a schedule, scopes it to the schemas you own, posts the invalid objects to Slack, applies the recompile only behind auto_remediate and dry_run, one statement at a time, then proves the result by reading dba_objects again. Every run keeps its logs, so you can see when objects went invalid and what fixed them.

Tested end to end

On Kestra 2.0.5 OSS against Oracle Database Free 23ai (gvenzl/oracle-free, service FREEPDB1), with a local HTTP sink standing in for Slack. The test schema APP held a table T1 and four objects built on its name column: a view V1, a procedure P1, a package body PKG1 and a trigger TRG1.

Run Setup and inputs Result
1 all objects VALID, defaults 0 invalid, clean branch, SUCCESS
2 ALTER TABLE T1 MODIFY name, defaults (dry_run: true) 4 invalid detected and posted to Slack, no change, SUCCESS. dba_objects still showed 4
3 same break, auto_remediate: true, dry_run: true Same report, Slack said no change applied, dba_objects still 4. The dry_run gate held
4 same break, auto_remediate: true, dry_run: false Recompiled, reaudit found 0, SUCCESS. dba_objects went from 4 to 0
5 ALTER TABLE T1 DROP COLUMN name, auto_remediate: true, dry_run: false 4 objects could not compile against the dropped column, reaudit still 4, the run FAILED and the errors block alerted Slack

Runs 1 and 2 are the proof the check can fail: the same audit returned 0 against the healthy schema and 4 against the broken one. Run 4 is the before and after, 4 down to 0, read from dba_objects by sqlplus not only from the Kestra log.

Prerequisites

  • An Oracle Database reachable over the thin JDBC driver (jdbc:oracle:thin:@//host:1521/service).
  • A database user that can read dba_objects (SELECT_CATALOG_ROLE or SELECT ANY DICTIONARY) and recompile the objects it finds. Recompiling another schema's objects needs ALTER ANY PROCEDURE, ALTER ANY TRIGGER and the matching privileges, which a DBA role already carries. A user recompiling only its own objects needs none of those.

Secrets

  • ORACLE_PASSWORD: the database password. It is the default for the password input.
  • SLACK_WEBHOOK_URL: used by alert and the errors block.
  • In Kestra OSS, provide each one as a base64-encoded environment variable prefixed SECRET_.

Inputs

Input Default Purpose
jdbc_url jdbc:oracle:thin:@//localhost:1521/FREEPDB1 The Oracle instance to check
username SYSTEM The database user
password {{ secret('ORACLE_PASSWORD') }} The database password
object_owners [APP] Schema owners whose objects are checked
auto_remediate false Allow ALTER ... COMPILE
dry_run true Must be false for a recompile to run

Quick start

  1. Add the ORACLE_PASSWORD and SLACK_WEBHOOK_URL secrets.
  2. Import the flow, set jdbc_url and username, then list the schemas to check in object_owners.
  3. Run it once with the defaults and read the invalid objects per schema.
  4. When you want it to fix them, run with auto_remediate: true and dry_run: false.
  5. Enable the daily trigger, which always runs in safe mode.

How to extend

  • Narrow or widen the object types checked, for example to leave materialized views out.
  • Replace the two fixed passes with UTL_RECOMP.RECOMP_SERIAL for large schemas.
  • Fail the run as soon as the first audit finds anything, for a read-only drift check with no recompile.
  • Loop over several instances to check every database from one flow.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.