How can I pg_dump a materialized view as a materialized view and not a table?
Asked Answered
C

1

9

I'm attempting to pg_dump (v9.3.4) from one db and pg_restore into another (v9.3.6). I have several materialized views (some with indexes and some with no indexes). One of my materialized views is being dumped as a table (I have confirmed this by looking at the pg_dump output). How can I get it to dump as a materialized view?

Here's what I see in my pg_dump output:

CREATE TABLE my_mv (
  /* ... */
);

/* ... */

CREATE INDEX my_mv_col_1_idx ON my_mv USING btree (col_1);

/* ... */

CREATE RULE "_RETURN" AS
    ON SELECT TO my_mv DO INSTEAD  WITH tmp_1 AS (

/* ... */

My other MVs look like this:

CREATE MATERIALIZED VIEW my_good_mv AS
  SELECT /* ... */
WITH NO DATA;

/* ... */

CREATE INDEX my_good_mv_job_col_1_idx ON my_good_mv USING btree (col_1);

/* ... */

REFRESH MATERIALIZED VIEW my_good_mv;

I've confirmed this is an MV:

xxx=# SELECT relkind FROM pg_class WHERE oid = 'public.my_mv'::regclass;
 relkind 
---------
 m
(1 row)

Here's the MV definition:

create materialized view mv_members
(
  id,
  state,
  tags,
  primary_job_function, job_functions,
  min_salary,
  current_level, current_employer, desired_employment_types, desired_org_sizes,
  years_of_pro_experience,
  current_location, current_location_parents, desired_locations, desired_location_parents,
  creation_date)
as
with wh as (
  select poach_id, employer
  from (
    select poach_id, employer, row_number() over (partition by poach_id order by employer) as n
    from work_histories
    where end_year is null) t
  where n = 1),
tags as (
  select parent_id as poach_id, array_remove(array_agg(tag), null) as tags
  from poach_tags
  group by poach_id),
jfns as (
  select poach_id, array_remove(array_agg(job_function_id), null) as job_functions
  from poach_job_functions
  group by poach_id),
pjf as (
  select poach_id, job_function_id
  from (
    select poach_id, job_function_id, row_number() over (partition by poach_id order by job_function_id) as n
    from poach_job_functions
    where is_primary = true) t
  where n = 1),
pdl as (
  select
    p.id as poach_id,
    case when p.desired_locations != '{}'
      then p.desired_locations
      else
        case when p.mapped_desired_locations is null
          then '{}'
          else p.mapped_desired_locations
        end
    end as desired_locations
  from poaches p),
pdla as (
  select pdl.poach_id, unnest(l.ancestors) as ancestor
  from pdl
  inner join locations l on l.id = any(pdl.desired_locations)),
min_salaries as (
  select p.id as poach_id,
  case when min_salary_min is not null
    then min_salary_min
    else
      case when min_salary_max is not null
        then 0 
        else
          case when current_salary_min is not null
            then current_salary_min
            else
              case when current_salary_max is not null
                then 0
                else null
              end
          end
      end
  end as min_salary
  from poaches p)
select
  p.id,
  s.state,
  coalesce(t.tags, '{}'),
  pjf.job_function_id,
  coalesce(jfns.job_functions, '{}') as job_functions,
  min_salaries.min_salary as min_salary,
  p.current_level,
  wh.employer,
  p.employment_types,
  p.desired_org_sizes,
  p.years_of_pro_experience,
  p.current_location_id as current_location,
  array_remove(array_append(cl.ancestors, p.current_location_id), null) as current_location_parents,
  pdl.desired_locations,
  array_remove(array_cat(array_agg(pdla.ancestor), pdl.desired_locations), null) as desired_location_parents,
  p.creation_date
from
  poaches p
  inner join entity_states s on p.id = s.entity_id and s.is_current = true
  inner join min_salaries on p.id = min_salaries.poach_id
  left outer join tags t on p.id = t.poach_id
  left outer join wh on p.id = wh.poach_id
  left outer join pjf on p.id = pjf.poach_id
  left outer join jfns on p.id = jfns.poach_id
  left outer join locations cl on p.current_location_id = cl.id
  left outer join pdl on p.id = pdl.poach_id
  left outer join pdla on p.id = pdla.poach_id
where p.is_active = true
group by p.id, s.state, t.tags, pjf.job_function_id, job_functions, min_salary, p.current_level, wh.employer, p.employment_types, p.desired_org_sizes, current_location, current_location_parents, pdl.desired_locations, p.creation_date;

create index on mv_members (state);
create index on mv_members (primary_job_function);
create index on mv_members (job_functions);
create index on mv_members (current_level);
create index on mv_members (desired_employment_types);
create index on mv_members (desired_org_sizes);
create index on mv_members (desired_locations);
create index on mv_members (desired_location_parents);
create index on mv_members (creation_date);
Cataplasm answered 21/4, 2015 at 21:49 Comment(10)
Is it a MV? What do you get for SELECT relkind FROM pg_class WHERE oid = 'public.my_mv'::regclass? m or r? In older versions of Postgres MVs were implemented as table and updated by hand, maybe this is a piece of legacy?Mccraw
I get back m (see my edited question). I'm assuming m is for materialized view?Cataplasm
Yep. m is for MV. That's odd. I guess if you drop and recreate the object with standard CREATE MATERIALIZED VIEW syntax, the anomaly should go away.Mccraw
I've actually dropped and re-created several times already. But for kicks, I'll try again...Cataplasm
I am out of ideas. Did not see that myself, yet.Mccraw
Are you certain you are not using an older pg_dump? Check pg_dump --version. Also please show the original definition of the MV.Lucifer
I'm certain of the pg_dump version: v9.3.4Cataplasm
I added my MV definition in my original questionCataplasm
Try dumping just the schema (-s), and see if pg_dump is in fact turning it into a table.Theomachy
Looking at the code it should output TABLE by default. github.com/postgres/postgres/blob/REL9_3_4/src/bin/pg_dump/…, so somewhere relkind has become confused?Guillemot
D
0

A materialized view is 'technically' stored as a table object so when exported with pg_dump its treated as such. Its not possible to export using pg_dump as an MV

Deanedeaner answered 28/7, 2017 at 12:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.