viewy 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|