DEV Community

Michael
Michael

Posted on • Originally published at gbase.cn

GBase 8c Object Dependency Checks Before Schema Changes

The real challenge in a gbase database schema change isn't writing the DDL — it's uncovering every object that depends on the table before you hit “execute.” Many production incidents are caused not by syntax errors, but by overlooked views, triggers, or functions that silently break. This article uses PG_DEPEND, PG_REWRITE, PG_TRIGGER, and other system catalogs to build a structured pre‑change inspection routine.

Classifying Risk by Change Type

DDL Type Key Risk Recommended Approach
Add column Default values / NOT NULL can force a full table rewrite Add nullable column first, backfill in batches, then add constraints
Drop column Dependent objects may break; space is not reclaimed immediately Audit dependencies before physical removal
Alter column type Likely rewrites the entire table — heavy window, 2× disk usage Use a “new column” strategy for hot tables
Rename table / column Easy to miss application SQL, stored procedures Scan database objects, then application code
Drop table Maximum blast radius; CASCADE misuse is hard to undo List all dependents explicitly

Before any change, answer two questions: Does this rewrite the whole table? and How many objects are attached upstream and downstream?

Core System Catalog Queries

Catalog / View Purpose
PG_TABLES Shows trigger existence, creation and last DDL time
PG_OBJECT Object creator and modification timestamps
PG_DEPEND Dependency map; deptype is critical
PG_REWRITE Traces view/rule references back to base tables
PG_VIEWS View definitions
PG_TRIGGER Trigger details, function, enabled status
PG_PROC Function / procedure source code and arguments

1. Check Object State and Recent Changes

SELECT schemaname, tablename, tableowner,
       hasindexes, hasrules, hastriggers,
       created, last_ddl_time
FROM pg_tables
WHERE schemaname = 'acct' AND tablename = 'txn_order';
Enter fullscreen mode Exit fullscreen mode

Add more detail with PG_OBJECT:

SELECT object_oid, object_type, creator,
       ctime, mtime, changecsn
FROM pg_object
WHERE object_oid = 'acct.txn_order'::regclass;
Enter fullscreen mode Exit fullscreen mode

Pay close attention to last_ddl_time and mtime — many surprises come from recent, undocumented modifications.

2. View Dependencies via PG_REWRITE

A simple text search on PG_VIEWS is not enough. Combine PG_DEPEND with PG_REWRITE to find every view that relies on the table.

SELECT n.nspname      AS dep_schema,
       c.relname      AS dep_view,
       r.rulename     AS rule_name,
       d.deptype
FROM pg_depend d
JOIN pg_rewrite r ON r.oid = d.objid
JOIN pg_class c   ON c.oid = r.ev_class
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE d.classid    = 'pg_rewrite'::regclass
  AND d.refclassid = 'pg_class'::regclass
  AND d.refobjid   = 'acct.txn_order'::regclass
ORDER BY 1, 2;
Enter fullscreen mode Exit fullscreen mode

If this query returns rows, avoid blunt operations like dropping a column or changing its type directly.

3. Triggers and Stored Procedures

Find all triggers on the table:

SELECT n.nspname        AS schema_name,
       c.relname        AS table_name,
       t.tgname         AS trigger_name,
       p.proname        AS trigger_func,
       t.tgenabled,
       t.tgisinternal
FROM pg_trigger t
JOIN pg_class c     ON c.oid = t.tgrelid
JOIN pg_namespace n ON n.oid = c.relnamespace
JOIN pg_proc p      ON p.oid = t.tgfoid
WHERE n.nspname = 'acct' AND c.relname = 'txn_order'
ORDER BY t.tgname;
Enter fullscreen mode Exit fullscreen mode

Search function/procedure source code for references:

SELECT n.nspname, p.proname, p.prokind,
       p.prosrc, p.proargsrc
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE p.prosrc ILIKE '%txn_order%'
   OR COALESCE(p.proargsrc, '') ILIKE '%txn_order%'
ORDER BY 1, 2;
Enter fullscreen mode Exit fullscreen mode

Remember: dynamically constructed SQL inside procedures won't appear here — application code must be audited separately.

4. Understanding deptype to Control Cascade Risk

The deptype column in pg_depend is your safety switch:

deptype Meaning Strategy
n Normal dependency Requires CASCADE; must be manually confirmed
a Automatic dependency Removed with the parent
i Internal dependency Do not touch directly
p Pinned system dependency Off‑limits

Treat every n dependency as a mandatory review item. Never experiment with i or p in production.

Safer Alternative for Column Type Changes

For large tables, replacing a column is often safer than altering its type directly.

-- 1. Add the new column
ALTER TABLE acct.txn_order ADD COLUMN settle_ts_new timestamp;

-- 2. Backfill in batches
UPDATE acct.txn_order
   SET settle_ts_new = to_timestamp(settle_ts_old, 'YYYY-MM-DD HH24:MI:SS')
 WHERE settle_ts_old IS NOT NULL AND settle_ts_new IS NULL;

-- 3. Update dependent views to use the new column
CREATE OR REPLACE VIEW rpt.v_order_day AS
SELECT order_id, settle_ts_new AS settle_ts, amount, status_code
FROM acct.txn_order;

-- 4. After observation, drop the old column (optional)
Enter fullscreen mode Exit fullscreen mode

This breaks a high‑risk atomic change into observable, reversible steps.

Pre‑Change Audit Script

Log the dependency landscape right before the change window:

gsql -d finance_core -h 192.0.2.31 -p 5432 -U app_dba <<'SQL'
\o ddl_precheck_txn_order_20260402.log
SELECT now();

SELECT schemaname, tablename, hastriggers, created, last_ddl_time
FROM pg_tables
WHERE schemaname = 'acct' AND tablename = 'txn_order';

SELECT n.nspname, c.relname, r.rulename, d.deptype
FROM pg_depend d
JOIN pg_rewrite r ON r.oid = d.objid
JOIN pg_class c   ON c.oid = r.ev_class
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE d.classid    = 'pg_rewrite'::regclass
  AND d.refclassid = 'pg_class'::regclass
  AND d.refobjid   = 'acct.txn_order'::regclass
ORDER BY 1,2;

SELECT n.nspname, c.relname, t.tgname, p.proname, t.tgenabled
FROM pg_trigger t
JOIN pg_class c ON c.oid = t.tgrelid
JOIN pg_namespace n ON n.oid = c.relnamespace
JOIN pg_proc p ON p.oid = t.tgfoid
WHERE n.nspname = 'acct' AND c.relname = 'txn_order'
ORDER BY t.tgname;
\o
SQL
Enter fullscreen mode Exit fullscreen mode

Common Pitfalls

Pitfall Correct Approach
Only checking view names Always inspect PG_VIEWS.definition
Ignoring triggers Add table‑level trigger checks to every DDL review
Assuming DROP COLUMN frees space instantly Space reclamation is a separate operation
Using CASCADE casually Export the dependent object list before cascading
Checking only database objects Scan application SQL, ETL jobs, and report scripts as well

Summary

A table schema change is really a reorganization of object relationships. In GBase 8c, combining PG_DEPEND, PG_REWRITE, and PG_TRIGGER with a “dependencies first, cost assessment second, implementation path last” workflow catches most production surprises before they happen.

For any gbase database environment, making this pre‑check a habit turns risky DDL from a leap of faith into a controlled, predictable procedure.

Top comments (0)