Advertisement
Guest User

Untitled

a guest
Jul 24th, 2019
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PL/SQL 6.39 KB | None | 0 0
  1.  
  2. CREATE OR REPLACE FUNCTION f_dep_recursive(var text)
  3. returns  TABLE(
  4.     _level INTEGER,
  5.     _dep_name text,
  6.     _dep_table text,
  7.     _dep_type text,
  8.     _ref_name text,
  9.     _ref_type text)
  10. language plpgsql
  11. AS $$
  12.  
  13.    
  14.    
  15. BEGIN
  16.  
  17. CREATE temp   TABLE  tem (
  18.     _level INTEGER,
  19.     _dep_name text,
  20.     _dep_table text,
  21.     _dep_type text,
  22.     _ref_name text,
  23.     _ref_type text
  24. )ON COMMIT DROP ;
  25.  
  26.  
  27.  
  28. WITH RECURSIVE dep_recursive AS (
  29.  
  30.     -- Recursion: Initial Query
  31.     SELECT
  32.         0 AS "level",
  33.         var AS "dep_name",   --  <- define dependent object HERE
  34.         '' AS "dep_table",
  35.         '' AS "dep_type",
  36.         '' AS "ref_name",
  37.         '' AS "ref_type"
  38.  
  39.     UNION ALL
  40.  
  41.     -- Recursive Query
  42.     SELECT
  43.         LEVEL + 1 AS "level",
  44.         depedencies.dep_name,
  45.         depedencies.dep_table,
  46.         depedencies.dep_type,
  47.         depedencies.ref_name,
  48.         depedencies.ref_type
  49.     FROM (
  50.  
  51.         -- This function defines the type of any pg_class object
  52.         WITH classType AS (
  53.             SELECT
  54.                 oid,
  55.                 CASE relkind
  56.                     WHEN 'r' THEN 'TABLE'::text
  57.                     WHEN 'i' THEN 'INDEX'::text
  58.                     WHEN 'S' THEN 'SEQUENCE'::text
  59.                     WHEN 'v' THEN 'VIEW'::text
  60.                     WHEN 'c' THEN 'TYPE'::text      -- note: COMPOSITE type
  61.                     WHEN 't' THEN 'TABLE'::text     -- note: TOAST table
  62.                 END AS "type"
  63.             FROM pg_class
  64.         )
  65.  
  66.         -- Note: In pg_depend, the triple (classid,objid,objsubid) describes some object that depends
  67.         -- on the object described by the tuple (refclassid,refobjid).
  68.         -- So to drop the depending object, the referenced object (refclassid,refobjid) must be dropped first
  69.         SELECT DISTINCT
  70.             -- dep_name: Name of dependent object
  71.             CASE classid
  72.                 WHEN 'pg_class'::regclass THEN objid::regclass::text
  73.                 WHEN 'pg_type'::regclass THEN objid::regtype::text
  74.                 WHEN 'pg_proc'::regclass THEN objid::regprocedure::text
  75.                 WHEN 'pg_constraint'::regclass THEN (SELECT conname FROM pg_constraint WHERE OID = objid)
  76.                 WHEN 'pg_attrdef'::regclass THEN 'default'
  77.                 WHEN 'pg_rewrite'::regclass THEN (SELECT ev_class::regclass::text FROM pg_rewrite WHERE OID = objid)
  78.                 WHEN 'pg_trigger'::regclass THEN (SELECT tgname FROM pg_trigger WHERE OID = objid)
  79.                 ELSE objid::text
  80.             END AS "dep_name",
  81.             -- dep_table: Name of the table that is associated with the dependent object (for default values, triggers, rewrite rules)
  82.             CASE classid
  83.                 WHEN 'pg_constraint'::regclass THEN (SELECT conrelid::regclass::text FROM pg_constraint WHERE OID = objid)
  84.                 WHEN 'pg_attrdef'::regclass THEN (SELECT adrelid::regclass::text FROM pg_attrdef WHERE OID = objid)
  85.                 WHEN 'pg_trigger'::regclass THEN (SELECT tgrelid::regclass::text FROM pg_trigger WHERE OID = objid)
  86.                 ELSE ''
  87.             END AS "dep_table",
  88.             -- dep_type: Type of the dependent object (TABLE, FUNCTION, VIEW, TYPE, TRIGGER, ...)
  89.             CASE classid
  90.                 WHEN 'pg_class'::regclass THEN (SELECT TYPE FROM classType WHERE OID = objid)
  91.                 WHEN 'pg_type'::regclass THEN 'TYPE'
  92.                 WHEN 'pg_proc'::regclass THEN 'FUNCTION'
  93.                 WHEN 'pg_constraint'::regclass THEN 'TABLE CONSTRAINT'
  94.                 WHEN 'pg_attrdef'::regclass THEN 'TABLE DEFAULT'
  95.                 WHEN 'pg_rewrite'::regclass THEN (SELECT TYPE FROM classType WHERE OID = (SELECT ev_class FROM pg_rewrite WHERE OID = objid))
  96.                 WHEN 'pg_trigger'::regclass THEN 'TRIGGER'
  97.                 ELSE objid::text
  98.             END AS "dep_type",
  99.             -- ref_name: Name of referenced object (the object that depends on the dependent object)
  100.             CASE refclassid
  101.                 WHEN 'pg_class'::regclass THEN refobjid::regclass::text
  102.                 WHEN 'pg_type'::regclass THEN refobjid::regtype::text
  103.                 WHEN 'pg_proc'::regclass THEN refobjid::regprocedure::text
  104.                 ELSE refobjid::text
  105.             END AS "ref_name",
  106.             -- ref_type: Type of the referenced object (TABLE, FUNCTION, VIEW, TYPE, TRIGGER, ...)
  107.             CASE refclassid
  108.                 WHEN 'pg_class'::regclass THEN (SELECT TYPE FROM classType WHERE OID = refobjid)
  109.                 WHEN 'pg_type'::regclass THEN 'TYPE'
  110.                 WHEN 'pg_proc'::regclass THEN 'FUNCTION'
  111.                 ELSE refobjid::text
  112.             END AS "ref_type",
  113.             -- dependency type: Only 'normal' dependencies are relevant for DROP statements
  114.             CASE deptype
  115.                 WHEN 'n' THEN 'normal'
  116.                 WHEN 'a' THEN 'automatic'
  117.                 WHEN 'i' THEN 'internal'
  118.                 WHEN 'e' THEN 'extension'
  119.                 WHEN 'p' THEN 'pinned'
  120.             END AS "dependency type"
  121.         FROM pg_catalog.pg_depend
  122.         WHERE deptype = 'n'                 -- look at normal dependencies only
  123.         AND refclassid NOT IN (2615, 2612)  -- schema and language are ignored as dependencies
  124.  
  125.     ) depedencies
  126.     -- Recursion: Join with results of last query, search for dependencies recursively
  127.     JOIN dep_recursive ON (dep_recursive.dep_name = depedencies.ref_name)
  128.     WHERE depedencies.ref_name NOT IN(depedencies.dep_name, depedencies.dep_table) -- no self-references
  129.  
  130. )
  131.  
  132.  
  133.  
  134.  
  135. -- Select and filter the results of the recursive query
  136. INSERT INTO tem SELECT
  137.     MAX(LEVEL) AS "level",          -- drop highest level first, so no other objects depend on it
  138.     dep_name,                       -- the object to drop
  139.     MIN(dep_table) AS "dep_table",  -- the table that is associated with this object (constraints, triggers)
  140.     MIN(dep_type) AS "dep_type",    -- the type of this object
  141.     string_agg(ref_name, ', ') AS "ref_names",   -- list of objects that depend on this (just FYI)
  142.     string_agg(ref_type, ', ') AS "ref_types"    -- list of their respective types (just FYI)
  143. FROM dep_recursive
  144. WHERE LEVEL > 0                  -- ignore the initial object (level 0)
  145. GROUP BY dep_name                -- ignore multiple references to dependent objects, dropping them once is enough
  146. ORDER BY LEVEL DESC, dep_name;   -- level descending: deepest dependency first
  147.  
  148.  
  149.  
  150. RETURN query (SELECT  * FROM tem);
  151.  
  152.  
  153.  
  154.  
  155. END $$;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement