viewy 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/db/migrate/20180525142127_add_schema_name_to_view_dependencies.rb +253 -0
- data/db/migrate/20180528165706_update_schema_name_in_view_dependencies.rb +302 -0
- data/lib/viewy/acts_as_materialized_view.rb +22 -5
- data/lib/viewy/acts_as_view.rb +5 -3
- data/lib/viewy/dependency_management/view_refresher.rb +1 -0
- data/lib/viewy/dependency_manager.rb +2 -1
- data/lib/viewy/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e543bb4e8b3ed6a0d0b17f2ac92b3baa855c69c1
|
4
|
+
data.tar.gz: ecc419c2a83e3af846c7194b77a600ffe08dc6f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c97f910f9b8c987d6ae7c0ff81c405ff809d2e60511103667594a62be0131ac068210540bfb6398dc1d13f6ecf4f3de960b075d4f8a380fb077e51b571982600
|
7
|
+
data.tar.gz: 7cb6479e27a908506fb6061c7fa9ae9e2270a1f06d42f086fed58385493a6580c27208e1476d9fb1fb163ab84d749d919d11f82df8ea4a9a31988b7535136dc2
|
@@ -0,0 +1,253 @@
|
|
1
|
+
class AddSchemaNameToViewDependencies < ActiveRecord::Migration[5.2]
|
2
|
+
def up
|
3
|
+
drop_statement = <<-SQL
|
4
|
+
DROP MATERIALIZED VIEW all_view_dependencies;
|
5
|
+
DROP MATERIALIZED VIEW materialized_view_dependencies;
|
6
|
+
DROP FUNCTION all_view_dependencies(name);
|
7
|
+
DROP FUNCTION view_dependencies(name);
|
8
|
+
SQL
|
9
|
+
execute(drop_statement)
|
10
|
+
|
11
|
+
view_dependencies_function_sql = <<-SQL
|
12
|
+
CREATE OR REPLACE FUNCTION view_dependencies(materialized_view NAME)
|
13
|
+
RETURNS TEXT[]
|
14
|
+
AS $$
|
15
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
16
|
+
SELECT oid, 1, ARRAY[oid], FALSE
|
17
|
+
FROM pg_class
|
18
|
+
WHERE relname = materialized_view
|
19
|
+
UNION
|
20
|
+
SELECT
|
21
|
+
dependents.refobjid,
|
22
|
+
dg.depth + 1,
|
23
|
+
dg.path || dependents.refobjid,
|
24
|
+
dependents.refobjid = ANY(dg.path)
|
25
|
+
FROM dependency_graph dg
|
26
|
+
JOIN pg_rewrite rewrites ON rewrites.ev_class = dg.oid
|
27
|
+
JOIN pg_depend dependents ON dependents.objid = rewrites.oid
|
28
|
+
WHERE NOT dg.cycle
|
29
|
+
), dependencies AS(
|
30
|
+
SELECT
|
31
|
+
pg_class.relname AS view_name,
|
32
|
+
schemas.nspname AS schema_name,
|
33
|
+
dependency_graph.OID,
|
34
|
+
MIN(depth) AS min_depth
|
35
|
+
FROM dependency_graph
|
36
|
+
LEFT JOIN pg_class ON pg_class.OID = dependency_graph.oid
|
37
|
+
LEFT JOIN pg_catalog.pg_namespace schemas ON schemas.oid = pg_class.relnamespace
|
38
|
+
GROUP BY dependency_graph.OID, pg_class.relname, schemas.nspname
|
39
|
+
ORDER BY min_depth
|
40
|
+
)
|
41
|
+
SELECT ARRAY(SELECT dependencies.schema_name || '.' || dependencies.view_name FROM
|
42
|
+
dependencies
|
43
|
+
JOIN pg_matviews
|
44
|
+
ON pg_matviews.matviewname = dependencies.view_name
|
45
|
+
AND pg_matviews.schemaname = dependencies.schema_name
|
46
|
+
WHERE dependencies.view_name != materialized_view)
|
47
|
+
;
|
48
|
+
$$ LANGUAGE SQL;
|
49
|
+
SQL
|
50
|
+
execute(view_dependencies_function_sql)
|
51
|
+
|
52
|
+
all_view_dependencies_function_sql = <<-SQL
|
53
|
+
CREATE OR REPLACE FUNCTION all_view_dependencies(materialized_view NAME)
|
54
|
+
RETURNS TEXT[]
|
55
|
+
AS $$
|
56
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
57
|
+
SELECT oid, 1, ARRAY[oid], FALSE
|
58
|
+
FROM pg_class
|
59
|
+
WHERE relname = materialized_view
|
60
|
+
UNION
|
61
|
+
SELECT
|
62
|
+
dependents.refobjid,
|
63
|
+
dg.depth + 1,
|
64
|
+
dg.path || dependents.refobjid,
|
65
|
+
dependents.refobjid = ANY(dg.path)
|
66
|
+
FROM dependency_graph dg
|
67
|
+
JOIN pg_rewrite rewrites ON rewrites.ev_class = dg.oid
|
68
|
+
JOIN pg_depend dependents ON dependents.objid = rewrites.oid
|
69
|
+
JOIN pg_class ON dependents.refobjid = pg_class.OID
|
70
|
+
JOIN pg_authid ON pg_class.relowner = pg_authid.OID AND pg_authid.rolname != 'postgres'
|
71
|
+
WHERE NOT dg.cycle AND pg_class.relkind IN ('m', 'v')
|
72
|
+
), dependencies AS(
|
73
|
+
SELECT
|
74
|
+
pg_class.relname AS view_name,
|
75
|
+
schemas.nspname AS schema_name,
|
76
|
+
dependency_graph.OID,
|
77
|
+
MIN(depth) AS min_depth
|
78
|
+
FROM dependency_graph
|
79
|
+
LEFT JOIN pg_class ON pg_class.OID = dependency_graph.oid
|
80
|
+
LEFT JOIN pg_catalog.pg_namespace schemas ON schemas.oid = pg_class.relnamespace
|
81
|
+
GROUP BY dependency_graph.OID, pg_class.relname, schemas.nspname
|
82
|
+
ORDER BY min_depth
|
83
|
+
)
|
84
|
+
SELECT ARRAY(
|
85
|
+
SELECT dependencies.schema_name || '.' || dependencies.view_name
|
86
|
+
FROM dependencies
|
87
|
+
LEFT JOIN pg_matviews
|
88
|
+
ON pg_matviews.matviewname = dependencies.view_name
|
89
|
+
AND pg_matviews.schemaname = dependencies.schema_name
|
90
|
+
LEFT JOIN pg_views
|
91
|
+
ON pg_views.viewname = dependencies.view_name
|
92
|
+
AND pg_views.schemaname = dependencies.schema_name
|
93
|
+
WHERE dependencies.view_name != materialized_view
|
94
|
+
)
|
95
|
+
;
|
96
|
+
$$ LANGUAGE SQL;
|
97
|
+
SQL
|
98
|
+
execute(all_view_dependencies_function_sql)
|
99
|
+
|
100
|
+
all_view_dependency_sql = <<-SQL
|
101
|
+
CREATE MATERIALIZED VIEW all_view_dependencies AS
|
102
|
+
WITH normal_view_dependencies AS (
|
103
|
+
SELECT
|
104
|
+
schemaname || '.' || viewname AS view_name,
|
105
|
+
all_view_dependencies(viewname) AS view_dependencies
|
106
|
+
FROM pg_views
|
107
|
+
WHERE viewowner != 'postgres'
|
108
|
+
),
|
109
|
+
matview_dependencies AS (
|
110
|
+
SELECT
|
111
|
+
schemaname || '.' || matviewname AS view_name,
|
112
|
+
all_view_dependencies(matviewname) AS view_dependencies
|
113
|
+
FROM pg_matviews
|
114
|
+
WHERE matviewowner != 'postgres'
|
115
|
+
)
|
116
|
+
SELECT matview_dependencies.*, TRUE as materialized_view FROM matview_dependencies
|
117
|
+
UNION
|
118
|
+
SELECT normal_view_dependencies.*, FALSE AS materialized_view FROM normal_view_dependencies;
|
119
|
+
SQL
|
120
|
+
execute(all_view_dependency_sql)
|
121
|
+
|
122
|
+
materialized_view_dependency_sql = <<-SQL
|
123
|
+
CREATE MATERIALIZED VIEW materialized_view_dependencies AS
|
124
|
+
SELECT
|
125
|
+
schemaname || '.' || matviewname AS view_name,
|
126
|
+
view_dependencies(matviewname),
|
127
|
+
TRUE AS materialized_view
|
128
|
+
FROM pg_matviews
|
129
|
+
WHERE matviewname != 'materialized_view_dependencies' AND matviewname != 'all_view_dependencies'
|
130
|
+
;
|
131
|
+
SQL
|
132
|
+
execute(materialized_view_dependency_sql)
|
133
|
+
end
|
134
|
+
|
135
|
+
def down
|
136
|
+
drop_statement = <<-SQL
|
137
|
+
DROP MATERIALIZED VIEW all_view_dependencies;
|
138
|
+
DROP MATERIALIZED VIEW materialized_view_dependencies;
|
139
|
+
DROP FUNCTION all_view_dependencies(name);
|
140
|
+
DROP FUNCTION view_dependencies(name);
|
141
|
+
SQL
|
142
|
+
execute(drop_statement)
|
143
|
+
|
144
|
+
view_dependencies_function_sql = <<-SQL
|
145
|
+
CREATE OR REPLACE FUNCTION view_dependencies(materialized_view NAME)
|
146
|
+
RETURNS NAME[]
|
147
|
+
AS $$
|
148
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
149
|
+
SELECT oid, 1, ARRAY[oid], FALSE
|
150
|
+
FROM pg_class
|
151
|
+
WHERE relname = materialized_view
|
152
|
+
UNION
|
153
|
+
SELECT
|
154
|
+
dependents.refobjid,
|
155
|
+
dg.depth + 1,
|
156
|
+
dg.path || dependents.refobjid,
|
157
|
+
dependents.refobjid = ANY(dg.path)
|
158
|
+
FROM dependency_graph dg
|
159
|
+
JOIN pg_rewrite rewrites ON rewrites.ev_class = dg.oid
|
160
|
+
JOIN pg_depend dependents ON dependents.objid = rewrites.oid
|
161
|
+
WHERE NOT dg.cycle
|
162
|
+
), dependencies AS(
|
163
|
+
SELECT
|
164
|
+
(SELECT relname FROM pg_class WHERE pg_class.OID = dependency_graph.oid) AS view_name,
|
165
|
+
dependency_graph.OID,
|
166
|
+
MIN(depth) AS min_depth
|
167
|
+
FROM dependency_graph
|
168
|
+
GROUP BY dependency_graph.OID ORDER BY min_depth
|
169
|
+
)
|
170
|
+
SELECT ARRAY(SELECT dependencies.view_name FROM
|
171
|
+
dependencies
|
172
|
+
JOIN pg_matviews ON pg_matviews.matviewname = dependencies.view_name
|
173
|
+
WHERE dependencies.view_name != materialized_view)
|
174
|
+
;
|
175
|
+
$$ LANGUAGE SQL;
|
176
|
+
SQL
|
177
|
+
execute(view_dependencies_function_sql)
|
178
|
+
|
179
|
+
all_view_dependencies_function_sql = <<-SQL
|
180
|
+
CREATE OR REPLACE FUNCTION all_view_dependencies(materialized_view NAME)
|
181
|
+
RETURNS NAME[]
|
182
|
+
AS $$
|
183
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
184
|
+
SELECT oid, 1, ARRAY[oid], FALSE
|
185
|
+
FROM pg_class
|
186
|
+
WHERE relname = materialized_view
|
187
|
+
UNION
|
188
|
+
SELECT
|
189
|
+
dependents.refobjid,
|
190
|
+
dg.depth + 1,
|
191
|
+
dg.path || dependents.refobjid,
|
192
|
+
dependents.refobjid = ANY(dg.path)
|
193
|
+
FROM dependency_graph dg
|
194
|
+
JOIN pg_rewrite rewrites ON rewrites.ev_class = dg.oid
|
195
|
+
JOIN pg_depend dependents ON dependents.objid = rewrites.oid
|
196
|
+
JOIN pg_class ON dependents.refobjid = pg_class.OID
|
197
|
+
JOIN pg_authid ON pg_class.relowner = pg_authid.OID AND pg_authid.rolname != 'postgres'
|
198
|
+
WHERE NOT dg.cycle AND pg_class.relkind IN ('m', 'v')
|
199
|
+
), dependencies AS(
|
200
|
+
SELECT
|
201
|
+
(SELECT relname FROM pg_class WHERE pg_class.OID = dependency_graph.oid) AS view_name,
|
202
|
+
dependency_graph.OID,
|
203
|
+
MIN(depth) AS min_depth
|
204
|
+
FROM dependency_graph
|
205
|
+
GROUP BY dependency_graph.OID ORDER BY min_depth
|
206
|
+
)
|
207
|
+
SELECT ARRAY(
|
208
|
+
SELECT dependencies.view_name
|
209
|
+
FROM dependencies
|
210
|
+
LEFT JOIN pg_matviews ON pg_matviews.matviewname = dependencies.view_name
|
211
|
+
LEFT JOIN pg_views ON pg_views.viewname = dependencies.view_name
|
212
|
+
WHERE dependencies.view_name != materialized_view
|
213
|
+
)
|
214
|
+
;
|
215
|
+
$$ LANGUAGE SQL;
|
216
|
+
SQL
|
217
|
+
execute(all_view_dependencies_function_sql)
|
218
|
+
|
219
|
+
all_view_dependency_sql = <<-SQL
|
220
|
+
CREATE MATERIALIZED VIEW all_view_dependencies AS
|
221
|
+
WITH normal_view_dependencies AS (
|
222
|
+
SELECT
|
223
|
+
viewname AS view_name,
|
224
|
+
all_view_dependencies(viewname) AS view_dependencies
|
225
|
+
FROM pg_views
|
226
|
+
WHERE viewowner != 'postgres'
|
227
|
+
),
|
228
|
+
matview_dependencies AS (
|
229
|
+
SELECT
|
230
|
+
matviewname AS view_name,
|
231
|
+
all_view_dependencies(matviewname) AS view_dependencies
|
232
|
+
FROM pg_matviews
|
233
|
+
WHERE matviewowner != 'postgres'
|
234
|
+
)
|
235
|
+
SELECT matview_dependencies.*, TRUE as materialized_view FROM matview_dependencies
|
236
|
+
UNION
|
237
|
+
SELECT normal_view_dependencies.*, FALSE AS materialized_view FROM normal_view_dependencies;
|
238
|
+
SQL
|
239
|
+
execute(all_view_dependency_sql)
|
240
|
+
|
241
|
+
materialized_view_dependency_sql = <<-SQL
|
242
|
+
CREATE MATERIALIZED VIEW materialized_view_dependencies AS
|
243
|
+
SELECT
|
244
|
+
matviewname AS view_name,
|
245
|
+
view_dependencies(matviewname),
|
246
|
+
TRUE AS materialized_view
|
247
|
+
FROM pg_matviews
|
248
|
+
WHERE matviewname != 'materialized_view_dependencies' AND matviewname != 'all_view_dependencies'
|
249
|
+
;
|
250
|
+
SQL
|
251
|
+
execute(materialized_view_dependency_sql)
|
252
|
+
end
|
253
|
+
end
|
@@ -0,0 +1,302 @@
|
|
1
|
+
class UpdateSchemaNameInViewDependencies < ActiveRecord::Migration[5.0]
|
2
|
+
|
3
|
+
def up
|
4
|
+
drop_statement = <<-SQL
|
5
|
+
DROP MATERIALIZED VIEW all_view_dependencies;
|
6
|
+
DROP MATERIALIZED VIEW materialized_view_dependencies;
|
7
|
+
DROP FUNCTION all_view_dependencies(name);
|
8
|
+
DROP FUNCTION view_dependencies(name);
|
9
|
+
SQL
|
10
|
+
execute(drop_statement)
|
11
|
+
|
12
|
+
view_dependencies_function_sql = <<-SQL
|
13
|
+
CREATE OR REPLACE FUNCTION view_dependencies(materialized_view NAME, view_schema NAME)
|
14
|
+
RETURNS TEXT[]
|
15
|
+
AS $$
|
16
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
17
|
+
SELECT pg_class.oid, 1, ARRAY[pg_class.oid], FALSE
|
18
|
+
FROM pg_class
|
19
|
+
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.OID AND pg_namespace.nspname = view_schema
|
20
|
+
WHERE relname = materialized_view
|
21
|
+
UNION
|
22
|
+
SELECT
|
23
|
+
dependents.refobjid,
|
24
|
+
dg.depth + 1,
|
25
|
+
dg.path || dependents.refobjid,
|
26
|
+
dependents.refobjid = ANY(dg.path)
|
27
|
+
FROM dependency_graph dg
|
28
|
+
JOIN pg_rewrite rewrites ON rewrites.ev_class = dg.oid
|
29
|
+
JOIN pg_depend dependents ON dependents.objid = rewrites.oid
|
30
|
+
WHERE NOT dg.cycle
|
31
|
+
), dependencies AS(
|
32
|
+
SELECT
|
33
|
+
(
|
34
|
+
SELECT
|
35
|
+
nspname || '.' || relname
|
36
|
+
FROM pg_class
|
37
|
+
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.OID
|
38
|
+
WHERE pg_class.OID = dependency_graph.oid
|
39
|
+
) AS view_name,
|
40
|
+
(
|
41
|
+
SELECT
|
42
|
+
nspname
|
43
|
+
FROM pg_class
|
44
|
+
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.OID
|
45
|
+
WHERE pg_class.OID = dependency_graph.oid
|
46
|
+
) AS schema_name,
|
47
|
+
(
|
48
|
+
SELECT
|
49
|
+
relname
|
50
|
+
FROM pg_class
|
51
|
+
WHERE pg_class.OID = dependency_graph.oid
|
52
|
+
) AS name,
|
53
|
+
dependency_graph.OID,
|
54
|
+
MIN(depth) AS min_depth
|
55
|
+
FROM dependency_graph
|
56
|
+
GROUP BY dependency_graph.OID
|
57
|
+
ORDER BY min_depth
|
58
|
+
)
|
59
|
+
SELECT ARRAY(
|
60
|
+
SELECT dependencies.view_name
|
61
|
+
FROM dependencies
|
62
|
+
JOIN pg_matviews ON pg_matviews.matviewname = dependencies.name AND pg_matviews.schemaname = dependencies.schema_name
|
63
|
+
WHERE dependencies.view_name != (view_schema || '.' || materialized_view)
|
64
|
+
)
|
65
|
+
;
|
66
|
+
$$ LANGUAGE SQL;
|
67
|
+
SQL
|
68
|
+
execute(view_dependencies_function_sql)
|
69
|
+
|
70
|
+
all_view_dependencies_function_sql = <<-SQL
|
71
|
+
CREATE OR REPLACE FUNCTION all_view_dependencies(materialized_view NAME, view_schema NAME)
|
72
|
+
RETURNS TEXT[]
|
73
|
+
AS $$
|
74
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
75
|
+
SELECT pg_class.oid, 1, ARRAY[pg_class.oid], FALSE
|
76
|
+
FROM pg_class
|
77
|
+
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.OID AND pg_namespace.nspname = view_schema
|
78
|
+
WHERE relname = materialized_view
|
79
|
+
UNION
|
80
|
+
SELECT
|
81
|
+
dependents.refobjid,
|
82
|
+
dg.depth + 1,
|
83
|
+
dg.path || dependents.refobjid,
|
84
|
+
dependents.refobjid = ANY(dg.path)
|
85
|
+
FROM dependency_graph dg
|
86
|
+
JOIN pg_rewrite rewrites ON rewrites.ev_class = dg.oid
|
87
|
+
JOIN pg_depend dependents ON dependents.objid = rewrites.oid
|
88
|
+
JOIN pg_class ON dependents.refobjid = pg_class.OID
|
89
|
+
JOIN pg_authid ON pg_class.relowner = pg_authid.OID AND pg_authid.rolname != 'postgres'
|
90
|
+
WHERE NOT dg.cycle AND pg_class.relkind IN ('m', 'v')
|
91
|
+
), dependencies AS(
|
92
|
+
SELECT
|
93
|
+
(
|
94
|
+
SELECT
|
95
|
+
nspname || '.' || relname
|
96
|
+
FROM pg_class
|
97
|
+
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.OID
|
98
|
+
WHERE pg_class.OID = dependency_graph.oid
|
99
|
+
) AS view_name,
|
100
|
+
(
|
101
|
+
SELECT
|
102
|
+
nspname
|
103
|
+
FROM pg_class
|
104
|
+
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.OID
|
105
|
+
WHERE pg_class.OID = dependency_graph.oid
|
106
|
+
) AS schema_name,
|
107
|
+
(
|
108
|
+
SELECT
|
109
|
+
relname
|
110
|
+
FROM pg_class
|
111
|
+
WHERE pg_class.OID = dependency_graph.oid
|
112
|
+
) AS name,
|
113
|
+
dependency_graph.OID,
|
114
|
+
MIN(depth) AS min_depth
|
115
|
+
FROM dependency_graph
|
116
|
+
GROUP BY dependency_graph.OID
|
117
|
+
ORDER BY min_depth
|
118
|
+
)
|
119
|
+
SELECT ARRAY(
|
120
|
+
SELECT dependencies.view_name
|
121
|
+
FROM dependencies
|
122
|
+
LEFT JOIN pg_matviews
|
123
|
+
ON pg_matviews.matviewname = dependencies.name
|
124
|
+
AND pg_matviews.schemaname = dependencies.schema_name
|
125
|
+
LEFT JOIN pg_views
|
126
|
+
ON pg_views.viewname = dependencies.name
|
127
|
+
AND pg_matviews.schemaname = dependencies.schema_name
|
128
|
+
WHERE dependencies.view_name != (view_schema || '.' || materialized_view)
|
129
|
+
)
|
130
|
+
;
|
131
|
+
$$ LANGUAGE SQL;
|
132
|
+
SQL
|
133
|
+
execute(all_view_dependencies_function_sql)
|
134
|
+
|
135
|
+
all_view_dependency_sql = <<-SQL
|
136
|
+
CREATE MATERIALIZED VIEW all_view_dependencies AS
|
137
|
+
WITH normal_view_dependencies AS (
|
138
|
+
SELECT
|
139
|
+
schemaname || '.' || viewname AS view_name,
|
140
|
+
all_view_dependencies(viewname, schemaname) AS view_dependencies
|
141
|
+
FROM pg_views
|
142
|
+
WHERE viewowner != 'postgres'
|
143
|
+
),
|
144
|
+
matview_dependencies AS (
|
145
|
+
SELECT
|
146
|
+
schemaname || '.' || matviewname AS view_name,
|
147
|
+
all_view_dependencies(matviewname, schemaname) AS view_dependencies
|
148
|
+
FROM pg_matviews
|
149
|
+
WHERE matviewowner != 'postgres'
|
150
|
+
)
|
151
|
+
SELECT matview_dependencies.*, TRUE as materialized_view FROM matview_dependencies
|
152
|
+
UNION
|
153
|
+
SELECT normal_view_dependencies.*, FALSE AS materialized_view FROM normal_view_dependencies;
|
154
|
+
SQL
|
155
|
+
execute(all_view_dependency_sql)
|
156
|
+
|
157
|
+
materialized_view_dependency_sql = <<-SQL
|
158
|
+
CREATE MATERIALIZED VIEW materialized_view_dependencies AS
|
159
|
+
SELECT
|
160
|
+
schemaname || '.' || matviewname AS view_name,
|
161
|
+
view_dependencies(matviewname, schemaname),
|
162
|
+
TRUE AS materialized_view
|
163
|
+
FROM pg_matviews
|
164
|
+
WHERE matviewname != 'materialized_view_dependencies' AND matviewname != 'all_view_dependencies'
|
165
|
+
;
|
166
|
+
SQL
|
167
|
+
execute(materialized_view_dependency_sql)
|
168
|
+
end
|
169
|
+
|
170
|
+
def down
|
171
|
+
drop_statement = <<-SQL
|
172
|
+
DROP MATERIALIZED VIEW all_view_dependencies;
|
173
|
+
DROP MATERIALIZED VIEW materialized_view_dependencies;
|
174
|
+
DROP FUNCTION all_view_dependencies(name, name);
|
175
|
+
DROP FUNCTION view_dependencies(name, name);
|
176
|
+
SQL
|
177
|
+
execute(drop_statement)
|
178
|
+
|
179
|
+
view_dependencies_function_sql = <<-SQL
|
180
|
+
CREATE OR REPLACE FUNCTION view_dependencies(materialized_view NAME)
|
181
|
+
RETURNS TEXT[]
|
182
|
+
AS $$
|
183
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
184
|
+
SELECT oid, 1, ARRAY[oid], FALSE
|
185
|
+
FROM pg_class
|
186
|
+
WHERE relname = materialized_view
|
187
|
+
UNION
|
188
|
+
SELECT
|
189
|
+
dependents.refobjid,
|
190
|
+
dg.depth + 1,
|
191
|
+
dg.path || dependents.refobjid,
|
192
|
+
dependents.refobjid = ANY(dg.path)
|
193
|
+
FROM dependency_graph dg
|
194
|
+
JOIN pg_rewrite rewrites ON rewrites.ev_class = dg.oid
|
195
|
+
JOIN pg_depend dependents ON dependents.objid = rewrites.oid
|
196
|
+
WHERE NOT dg.cycle
|
197
|
+
), dependencies AS(
|
198
|
+
SELECT
|
199
|
+
pg_class.relname AS view_name,
|
200
|
+
schemas.nspname AS schema_name,
|
201
|
+
dependency_graph.OID,
|
202
|
+
MIN(depth) AS min_depth
|
203
|
+
FROM dependency_graph
|
204
|
+
LEFT JOIN pg_class ON pg_class.OID = dependency_graph.oid
|
205
|
+
LEFT JOIN pg_catalog.pg_namespace schemas ON schemas.oid = pg_class.relnamespace
|
206
|
+
GROUP BY dependency_graph.OID, pg_class.relname, schemas.nspname
|
207
|
+
ORDER BY min_depth
|
208
|
+
)
|
209
|
+
SELECT ARRAY(SELECT dependencies.schema_name || '.' || dependencies.view_name FROM
|
210
|
+
dependencies
|
211
|
+
JOIN pg_matviews
|
212
|
+
ON pg_matviews.matviewname = dependencies.view_name
|
213
|
+
AND pg_matviews.schemaname = dependencies.schema_name
|
214
|
+
WHERE dependencies.view_name != materialized_view)
|
215
|
+
;
|
216
|
+
$$ LANGUAGE SQL;
|
217
|
+
SQL
|
218
|
+
execute(view_dependencies_function_sql)
|
219
|
+
|
220
|
+
all_view_dependencies_function_sql = <<-SQL
|
221
|
+
CREATE OR REPLACE FUNCTION all_view_dependencies(materialized_view NAME)
|
222
|
+
RETURNS TEXT[]
|
223
|
+
AS $$
|
224
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
225
|
+
SELECT oid, 1, ARRAY[oid], FALSE
|
226
|
+
FROM pg_class
|
227
|
+
WHERE relname = materialized_view
|
228
|
+
UNION
|
229
|
+
SELECT
|
230
|
+
dependents.refobjid,
|
231
|
+
dg.depth + 1,
|
232
|
+
dg.path || dependents.refobjid,
|
233
|
+
dependents.refobjid = ANY(dg.path)
|
234
|
+
FROM dependency_graph dg
|
235
|
+
JOIN pg_rewrite rewrites ON rewrites.ev_class = dg.oid
|
236
|
+
JOIN pg_depend dependents ON dependents.objid = rewrites.oid
|
237
|
+
JOIN pg_class ON dependents.refobjid = pg_class.OID
|
238
|
+
JOIN pg_authid ON pg_class.relowner = pg_authid.OID AND pg_authid.rolname != 'postgres'
|
239
|
+
WHERE NOT dg.cycle AND pg_class.relkind IN ('m', 'v')
|
240
|
+
), dependencies AS(
|
241
|
+
SELECT
|
242
|
+
pg_class.relname AS view_name,
|
243
|
+
schemas.nspname AS schema_name,
|
244
|
+
dependency_graph.OID,
|
245
|
+
MIN(depth) AS min_depth
|
246
|
+
FROM dependency_graph
|
247
|
+
LEFT JOIN pg_class ON pg_class.OID = dependency_graph.oid
|
248
|
+
LEFT JOIN pg_catalog.pg_namespace schemas ON schemas.oid = pg_class.relnamespace
|
249
|
+
GROUP BY dependency_graph.OID, pg_class.relname, schemas.nspname
|
250
|
+
ORDER BY min_depth
|
251
|
+
)
|
252
|
+
SELECT ARRAY(
|
253
|
+
SELECT dependencies.schema_name || '.' || dependencies.view_name
|
254
|
+
FROM dependencies
|
255
|
+
LEFT JOIN pg_matviews
|
256
|
+
ON pg_matviews.matviewname = dependencies.view_name
|
257
|
+
AND pg_matviews.schemaname = dependencies.schema_name
|
258
|
+
LEFT JOIN pg_views
|
259
|
+
ON pg_views.viewname = dependencies.view_name
|
260
|
+
AND pg_views.schemaname = dependencies.schema_name
|
261
|
+
WHERE dependencies.view_name != materialized_view
|
262
|
+
)
|
263
|
+
;
|
264
|
+
$$ LANGUAGE SQL;
|
265
|
+
SQL
|
266
|
+
execute(all_view_dependencies_function_sql)
|
267
|
+
|
268
|
+
all_view_dependency_sql = <<-SQL
|
269
|
+
CREATE MATERIALIZED VIEW all_view_dependencies AS
|
270
|
+
WITH normal_view_dependencies AS (
|
271
|
+
SELECT
|
272
|
+
schemaname || '.' || viewname AS view_name,
|
273
|
+
all_view_dependencies(viewname) AS view_dependencies
|
274
|
+
FROM pg_views
|
275
|
+
WHERE viewowner != 'postgres'
|
276
|
+
),
|
277
|
+
matview_dependencies AS (
|
278
|
+
SELECT
|
279
|
+
schemaname || '.' || matviewname AS view_name,
|
280
|
+
all_view_dependencies(matviewname) AS view_dependencies
|
281
|
+
FROM pg_matviews
|
282
|
+
WHERE matviewowner != 'postgres'
|
283
|
+
)
|
284
|
+
SELECT matview_dependencies.*, TRUE as materialized_view FROM matview_dependencies
|
285
|
+
UNION
|
286
|
+
SELECT normal_view_dependencies.*, FALSE AS materialized_view FROM normal_view_dependencies;
|
287
|
+
SQL
|
288
|
+
execute(all_view_dependency_sql)
|
289
|
+
|
290
|
+
materialized_view_dependency_sql = <<-SQL
|
291
|
+
CREATE MATERIALIZED VIEW materialized_view_dependencies AS
|
292
|
+
SELECT
|
293
|
+
schemaname || '.' || matviewname AS view_name,
|
294
|
+
view_dependencies(matviewname),
|
295
|
+
TRUE AS materialized_view
|
296
|
+
FROM pg_matviews
|
297
|
+
WHERE matviewname != 'materialized_view_dependencies' AND matviewname != 'all_view_dependencies'
|
298
|
+
;
|
299
|
+
SQL
|
300
|
+
execute(materialized_view_dependency_sql)
|
301
|
+
end
|
302
|
+
end
|
@@ -13,7 +13,7 @@ module Viewy
|
|
13
13
|
# @return [PG::Result] the result of the refresh statement on the materialized view
|
14
14
|
def refresh!(concurrently: false)
|
15
15
|
refresher = Viewy::DependencyManagement::ViewRefresher.new(Viewy.connection)
|
16
|
-
refresher.refresh_materialized_view(
|
16
|
+
refresher.refresh_materialized_view(full_table_name, with_dependencies: true, concurrently: concurrently)
|
17
17
|
end
|
18
18
|
|
19
19
|
# Refreshes this view without refreshing any dependencies
|
@@ -23,14 +23,14 @@ module Viewy
|
|
23
23
|
# @return [PG::Result] the result of the refresh statement on the materialized view
|
24
24
|
def refresh_without_dependencies!(concurrently: false)
|
25
25
|
refresher = Viewy::DependencyManagement::ViewRefresher.new(Viewy.connection)
|
26
|
-
refresher.refresh_materialized_view(
|
26
|
+
refresher.refresh_materialized_view(full_table_name, with_dependencies: false, concurrently: concurrently)
|
27
27
|
end
|
28
28
|
|
29
29
|
# Provides an array of sorted view dependencies
|
30
30
|
#
|
31
31
|
# @return [Array<String>]
|
32
32
|
def sorted_view_dependencies
|
33
|
-
view_dep = Viewy::Models::MaterializedViewDependency.find(
|
33
|
+
view_dep = Viewy::Models::MaterializedViewDependency.find(full_table_name)
|
34
34
|
Viewy::DependencyManagement::ViewSorter.new.sorted_materialized_view_subset(view_names: view_dep.view_dependencies)
|
35
35
|
end
|
36
36
|
|
@@ -38,11 +38,28 @@ module Viewy
|
|
38
38
|
#
|
39
39
|
# @return [Boolean] true if the view has been populated, false if not
|
40
40
|
def populated?
|
41
|
-
|
42
|
-
SELECT ispopulated
|
41
|
+
query = <<-SQL
|
42
|
+
SELECT ispopulated
|
43
|
+
FROM pg_matviews
|
44
|
+
WHERE matviewname = '#{table_name}'
|
45
|
+
AND schemaname = '#{schema_name.chomp('.')}';
|
43
46
|
SQL
|
47
|
+
result = connection.execute query
|
44
48
|
ActiveRecord::Type::Boolean.new.cast(result.values[0][0])
|
45
49
|
end
|
50
|
+
|
51
|
+
private def full_table_name
|
52
|
+
"#{schema_name}#{table_name}"
|
53
|
+
end
|
54
|
+
|
55
|
+
private def schema_name
|
56
|
+
chunks = table_name.to_s.partition('.')
|
57
|
+
if chunks[2].present?
|
58
|
+
''
|
59
|
+
else
|
60
|
+
"#{connection.current_schema}."
|
61
|
+
end
|
62
|
+
end
|
46
63
|
end
|
47
64
|
end
|
48
65
|
end
|
data/lib/viewy/acts_as_view.rb
CHANGED
@@ -12,9 +12,11 @@ module Viewy
|
|
12
12
|
#
|
13
13
|
# @return [nil]
|
14
14
|
def refresh!
|
15
|
-
view_dep = Viewy::Models::
|
16
|
-
view_dep.view_dependencies
|
17
|
-
|
15
|
+
view_dep = Viewy::Models::ViewDependency.find(table_name)
|
16
|
+
deps = Viewy::DependencyManagement::ViewSorter.new.sorted_view_subset(view_names: view_dep.view_dependencies)
|
17
|
+
deps.each do |view_dependency|
|
18
|
+
materialized_view_dependency = Viewy::Models::MaterializedViewDependency.find_by(view_name: view_dependency)
|
19
|
+
ActiveRecord::Base.connection.execute("REFRESH MATERIALIZED VIEW #{view_dependency}") if materialized_view_dependency
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -23,12 +23,13 @@ module Viewy
|
|
23
23
|
# NOTE: this is provided as a convenience for managing dependencies, and the user should not expect that the
|
24
24
|
# re-created views will function if they rely on parts of the replaced view that are removed.
|
25
25
|
#
|
26
|
-
# @param view_name [String] the name of the view being replaced
|
26
|
+
# @param view_name [String] the name of the view being replaced (optionally schema-qualified)
|
27
27
|
# @param new_definition_sql [String] the SQL definition of the new view
|
28
28
|
#
|
29
29
|
# @raise [ActiveRecord::StatementInvalidError] raised if a dependent view is somehow not refreshed correctly
|
30
30
|
# @return [PG::Result] the result of the refresh statement on the materialized view
|
31
31
|
def replace_view(view_name, new_definition_sql, &block)
|
32
|
+
view_name = view_name.split('.').last
|
32
33
|
Viewy.connection.execute("SELECT replace_view('#{view_name}', $$#{new_definition_sql}$$)")
|
33
34
|
block.call if block_given?
|
34
35
|
end
|
data/lib/viewy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: viewy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emerson Huitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "<"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rspec-rails
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,6 +111,8 @@ files:
|
|
97
111
|
- db/migrate/20160513141153_add_index_recreation.rb
|
98
112
|
- db/migrate/20180518200311_update_view_dependencies_function.rb
|
99
113
|
- db/migrate/20180521162238_ensure_tables_are_excluded_as_dependencies.rb
|
114
|
+
- db/migrate/20180525142127_add_schema_name_to_view_dependencies.rb
|
115
|
+
- db/migrate/20180528165706_update_schema_name_in_view_dependencies.rb
|
100
116
|
- lib/tasks/viewy_tasks.rake
|
101
117
|
- lib/viewy.rb
|
102
118
|
- lib/viewy/acts_as_materialized_view.rb
|