Skip to content

Function body table/view references not tracked for dependency ordering #282

Description

@da77a

Function body table/view references not tracked for dependency ordering

pg-schema-diff version

v1.0.5

Problem

Functions that reference tables or views in their body (via FROM/JOIN clauses, or %ROWTYPE/%TYPE declarations) have no dependency edge to those objects. This causes functions to be ordered before the tables/views they reference:

ERROR: relation "myschema.mytable" does not exist (SQLSTATE 42P01)

This affects:

  • LANGUAGE sql functions — body is opaque text ($function$...$function$), PostgreSQL does not record table deps in pg_depend
  • LANGUAGE plpgsql functions — same, plus %ROWTYPE and type[] declarations in DECLARE blocks are resolved at runtime, not tracked in pg_depend

The HAS_UNTRACKABLE_DEPENDENCIES hazard is emitted for plpgsql functions, but no ordering attempt is made even when the information is available in the function definition text.

Patterns not tracked

  1. Schema-qualified FROM/JOIN: FROM schema.table_name or JOIN schema.view_name
  2. %ROWTYPE declarations: DECLARE r schema.view_name%ROWTYPE
  3. Array-of-composite declarations: DECLARE batch schema.view_name[]

All of these are visible in pg_get_functiondef() output.

Suggested fix

Something better than this - which I'm using as "good enough for now":

Supplementing pg_depend-based detection with text-based parsing of the function definition. Regex patterns:

(?i)\b(\w+)\.(\w+)(?:%ROWTYPE|\[\])     -- schema.name%ROWTYPE or schema.name[]
(?i)(?:FROM|JOIN)\s+(\w+)\.(\w+)\b      -- FROM/JOIN schema.name

Matches are added as TableDependencies on the function, which the existing vertex generator already wires correctly.

Reproducer

CREATE TABLE public.orders (id int PRIMARY KEY, total numeric);
CREATE VIEW public.order_summary AS SELECT id, total FROM public.orders WHERE total > 0;

CREATE FUNCTION public.process() RETURNS void LANGUAGE plpgsql AS $$
DECLARE r order_summary%ROWTYPE;
BEGIN
  FOR r IN SELECT * FROM order_summary LOOP NULL; END LOOP;
END; $$;

Plan from empty → target: function is ordered before view → apply fails with type "order_summary" does not exist.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions