viewy 0.0.9 → 0.0.10
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/20151005150022_update_dependency_views.rb +1 -1
- data/db/migrate/20160512173021_update_view_replace_function.rb +139 -0
- data/lib/tasks/viewy_tasks.rake +24 -0
- data/lib/viewy.rb +1 -0
- data/lib/viewy/dependency_manager.rb +2 -1
- data/lib/viewy/event_triggers.rb +17 -0
- data/lib/viewy/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7519012d78dc8bb9829b1240e3916e9a2b452631
|
4
|
+
data.tar.gz: d95c4be5a030addf42acb30e06699bad9738a1fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cad94ef6b55fbc24569d64fe7a46110ae2608beb7852ebe7f917f1dd34a4d6723cb93f2e20bb5f3ba705bc30953b9e86916ccd435c4c4e28c4fcae226b7fea7c
|
7
|
+
data.tar.gz: 2bb352187f487f89c2c07fcac9efa981c60b121927b8dc26e83500c68b2eecf80cac82c4321b0ccf66ea3430cecd4d4f2b8173d0d5683c12c1eb56f3e4388142
|
@@ -42,8 +42,8 @@ class UpdateDependencyViews < ActiveRecord::Migration
|
|
42
42
|
|
43
43
|
def down
|
44
44
|
dependency_sql = <<-SQL
|
45
|
-
DROP MATERIALIZED VIEW materialized_view_dependencies;
|
46
45
|
DROP MATERIALIZED VIEW all_view_dependencies;
|
46
|
+
DROP MATERIALIZED VIEW materialized_view_dependencies;
|
47
47
|
|
48
48
|
CREATE MATERIALIZED VIEW materialized_view_dependencies AS
|
49
49
|
WITH normal_view_dependencies AS (
|
@@ -0,0 +1,139 @@
|
|
1
|
+
class UpdateViewReplaceFunction < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
function_sql = <<-SQL
|
4
|
+
CREATE OR REPLACE FUNCTION replace_view(view_name TEXT, new_sql TEXT) RETURNS VOID AS $$
|
5
|
+
DECLARE
|
6
|
+
ordered_oids INTEGER[] := ARRAY(
|
7
|
+
SELECT oid FROM
|
8
|
+
(
|
9
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
10
|
+
SELECT oid, 1, ARRAY[oid], FALSE
|
11
|
+
FROM pg_class
|
12
|
+
WHERE relname = view_name
|
13
|
+
UNION
|
14
|
+
SELECT
|
15
|
+
rewrites.ev_class,
|
16
|
+
dg.depth + 1,
|
17
|
+
dg.path || rewrites.ev_class,
|
18
|
+
rewrites.ev_class = ANY(dg.path)
|
19
|
+
FROM dependency_graph dg
|
20
|
+
JOIN pg_depend dependents ON dependents.refobjid = dg.oid
|
21
|
+
JOIN pg_rewrite rewrites ON rewrites.oid = dependents.objid
|
22
|
+
WHERE NOT dg.cycle
|
23
|
+
)
|
24
|
+
SELECT dependency_graph.OID, MIN(depth) AS min_depth FROM dependency_graph GROUP BY dependency_graph.OID ORDER BY min_depth
|
25
|
+
) ordered_dependents
|
26
|
+
);
|
27
|
+
create_statements TEXT[] := '{}';
|
28
|
+
current_statement TEXT;
|
29
|
+
view_drop_statement TEXT;
|
30
|
+
object_id INT;
|
31
|
+
BEGIN
|
32
|
+
FOREACH object_id IN ARRAY ordered_oids LOOP
|
33
|
+
SELECT
|
34
|
+
(CASE
|
35
|
+
WHEN (SELECT TRUE FROM pg_views WHERE viewname = relname) THEN
|
36
|
+
'CREATE OR REPLACE VIEW ' || pg_class.relname || ' AS ' || pg_get_viewdef(oid)
|
37
|
+
WHEN (SELECT TRUE FROM pg_matviews WHERE matviewname = relname) THEN
|
38
|
+
'CREATE MATERIALIZED VIEW ' || pg_class.relname || ' AS ' || pg_get_viewdef(oid) || ' WITH NO DATA'
|
39
|
+
END)
|
40
|
+
INTO current_statement
|
41
|
+
FROM pg_class
|
42
|
+
WHERE oid = object_id
|
43
|
+
AND pg_class.relname != view_name;
|
44
|
+
IF current_statement IS NOT NULL THEN
|
45
|
+
create_statements = create_statements || current_statement;
|
46
|
+
END IF;
|
47
|
+
END LOOP;
|
48
|
+
ALTER EVENT TRIGGER view_dependencies_update DISABLE;
|
49
|
+
SELECT
|
50
|
+
(
|
51
|
+
CASE
|
52
|
+
WHEN (SELECT TRUE FROM pg_views WHERE viewname = view_name) THEN
|
53
|
+
'DROP VIEW ' || view_name || ' CASCADE;'
|
54
|
+
WHEN (SELECT TRUE FROM pg_matviews WHERE matviewname = view_name) THEN
|
55
|
+
'DROP MATERIALIZED VIEW ' || view_name || ' CASCADE;'
|
56
|
+
END
|
57
|
+
)
|
58
|
+
INTO view_drop_statement;
|
59
|
+
EXECUTE view_drop_statement;
|
60
|
+
EXECUTE new_sql;
|
61
|
+
FOREACH current_statement IN ARRAY create_statements LOOP
|
62
|
+
EXECUTE current_statement;
|
63
|
+
END LOOP;
|
64
|
+
ALTER EVENT TRIGGER view_dependencies_update ENABLE ALWAYS;
|
65
|
+
END;
|
66
|
+
$$ LANGUAGE plpgsql;
|
67
|
+
SQL
|
68
|
+
execute function_sql
|
69
|
+
end
|
70
|
+
|
71
|
+
def down
|
72
|
+
function_sql = <<-SQL
|
73
|
+
CREATE OR REPLACE FUNCTION replace_view(view_name TEXT, new_sql TEXT) RETURNS VOID AS $$
|
74
|
+
DECLARE
|
75
|
+
ordered_oids INTEGER[] := ARRAY(
|
76
|
+
SELECT oid FROM
|
77
|
+
(
|
78
|
+
WITH RECURSIVE dependency_graph(oid, depth, path, cycle) AS (
|
79
|
+
SELECT oid, 1, ARRAY[oid], FALSE
|
80
|
+
FROM pg_class
|
81
|
+
WHERE relname = view_name
|
82
|
+
UNION
|
83
|
+
SELECT
|
84
|
+
rewrites.ev_class,
|
85
|
+
dg.depth + 1,
|
86
|
+
dg.path || rewrites.ev_class,
|
87
|
+
rewrites.ev_class = ANY(dg.path)
|
88
|
+
FROM dependency_graph dg
|
89
|
+
JOIN pg_depend dependents ON dependents.refobjid = dg.oid
|
90
|
+
JOIN pg_rewrite rewrites ON rewrites.oid = dependents.objid
|
91
|
+
WHERE NOT dg.cycle
|
92
|
+
)
|
93
|
+
SELECT dependency_graph.OID, MIN(depth) AS min_depth FROM dependency_graph GROUP BY dependency_graph.OID ORDER BY min_depth
|
94
|
+
) ordered_dependents
|
95
|
+
);
|
96
|
+
create_statements TEXT[] := '{}';
|
97
|
+
current_statement TEXT;
|
98
|
+
view_drop_statement TEXT;
|
99
|
+
object_id INT;
|
100
|
+
BEGIN
|
101
|
+
FOREACH object_id IN ARRAY ordered_oids LOOP
|
102
|
+
SELECT
|
103
|
+
(CASE
|
104
|
+
WHEN (SELECT TRUE FROM pg_views WHERE viewname = relname) THEN
|
105
|
+
'CREATE OR REPLACE VIEW ' || pg_class.relname || ' AS ' || pg_get_viewdef(oid)
|
106
|
+
WHEN (SELECT TRUE FROM pg_matviews WHERE matviewname = relname) THEN
|
107
|
+
'CREATE MATERIALIZED VIEW ' || pg_class.relname || ' AS ' || pg_get_viewdef(oid)
|
108
|
+
END)
|
109
|
+
INTO current_statement
|
110
|
+
FROM pg_class
|
111
|
+
WHERE oid = object_id
|
112
|
+
AND pg_class.relname != view_name;
|
113
|
+
IF current_statement IS NOT NULL THEN
|
114
|
+
create_statements = create_statements || current_statement;
|
115
|
+
END IF;
|
116
|
+
END LOOP;
|
117
|
+
ALTER EVENT TRIGGER view_dependencies_update DISABLE;
|
118
|
+
SELECT
|
119
|
+
(
|
120
|
+
CASE
|
121
|
+
WHEN (SELECT TRUE FROM pg_views WHERE viewname = view_name) THEN
|
122
|
+
'DROP VIEW ' || view_name || ' CASCADE;'
|
123
|
+
WHEN (SELECT TRUE FROM pg_matviews WHERE matviewname = view_name) THEN
|
124
|
+
'DROP MATERIALIZED VIEW ' || view_name || ' CASCADE;'
|
125
|
+
END
|
126
|
+
)
|
127
|
+
INTO view_drop_statement;
|
128
|
+
EXECUTE view_drop_statement;
|
129
|
+
EXECUTE new_sql;
|
130
|
+
FOREACH current_statement IN ARRAY create_statements LOOP
|
131
|
+
EXECUTE current_statement;
|
132
|
+
END LOOP;
|
133
|
+
ALTER EVENT TRIGGER view_dependencies_update ENABLE ALWAYS;
|
134
|
+
END;
|
135
|
+
$$ LANGUAGE plpgsql;
|
136
|
+
SQL
|
137
|
+
execute function_sql
|
138
|
+
end
|
139
|
+
end
|
data/lib/tasks/viewy_tasks.rake
CHANGED
@@ -5,4 +5,28 @@ namespace :viewy do
|
|
5
5
|
Viewy.refresh_all_dependency_information
|
6
6
|
puts 'View dependency information refresh complete.'
|
7
7
|
end
|
8
|
+
|
9
|
+
task :include_triggers_in_structure, :environment do
|
10
|
+
version_sql = <<-SQL
|
11
|
+
SHOW server_version;
|
12
|
+
SQL
|
13
|
+
result = Viewy.connection.execute(version_sql)
|
14
|
+
unless result.values[0][0].match(/9\.4/)
|
15
|
+
puts 'Updating structure.sql to include event triggers'
|
16
|
+
path = File.expand_path('db/structure.sql', Rails.root)
|
17
|
+
File.open(path, 'a') do |structure_sql|
|
18
|
+
event_triggers = Viewy::EventTriggers.new
|
19
|
+
structure_sql.puts
|
20
|
+
structure_sql.puts event_triggers.event_triggers_sql
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Rake::Task['db:structure:dump'].enhance do
|
27
|
+
if Rake::Task.task_defined?('viewy:include_triggers_in_structure')
|
28
|
+
Rake::Task['viewy:include_triggers_in_structure'].invoke
|
29
|
+
else
|
30
|
+
Rake::Task['app:viewy:include_triggers_in_structure'].invoke
|
31
|
+
end
|
8
32
|
end
|
data/lib/viewy.rb
CHANGED
@@ -4,6 +4,7 @@ require 'viewy/acts_as_view'
|
|
4
4
|
require 'viewy/acts_as_materialized_view'
|
5
5
|
require 'viewy/dependency_management'
|
6
6
|
require 'viewy/dependency_manager'
|
7
|
+
require 'viewy/event_triggers'
|
7
8
|
|
8
9
|
# Viewy provides a means of interacting with views in a Postgres database in a way that allows the manipulation
|
9
10
|
# of views and their dependencies
|
@@ -28,8 +28,9 @@ module Viewy
|
|
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
|
-
def replace_view(view_name, new_definition_sql)
|
31
|
+
def replace_view(view_name, new_definition_sql, &block)
|
32
32
|
Viewy.connection.execute("SELECT replace_view('#{view_name}', $$#{new_definition_sql}$$)")
|
33
|
+
block.call if block_given?
|
33
34
|
end
|
34
35
|
|
35
36
|
# @return [Viewy::DependencyManagement::ViewRefresher] a memoized view refresher object
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Viewy
|
2
|
+
# This provides a handle for dealing with Viewy specific event triggers, which are no longer exported from Postgres as of 9.5.1
|
3
|
+
# See http://www.postgresql.org/message-id/8795.1452631064@sss.pgh.pa.us for more information
|
4
|
+
#
|
5
|
+
# NOTE: this should be updated any time a migration changes the triggers
|
6
|
+
class EventTriggers
|
7
|
+
# @return [String] the sql needed to create the view triggers needed for viewy to function
|
8
|
+
def event_triggers_sql
|
9
|
+
<<-SQL
|
10
|
+
CREATE EVENT TRIGGER view_dependencies_update
|
11
|
+
ON DDL_COMMAND_END
|
12
|
+
WHEN TAG IN ('DROP VIEW', 'DROP MATERIALIZED VIEW', 'CREATE VIEW', 'CREATE MATERIALIZED VIEW', 'ALTER VIEW', 'ALTER MATERIALIZED VIEW')
|
13
|
+
EXECUTE PROCEDURE refresh_materialized_view_dependencies();
|
14
|
+
SQL
|
15
|
+
end
|
16
|
+
end
|
17
|
+
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.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emerson Huitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- db/migrate/20150929144540_add_view_replace_function.rb
|
81
81
|
- db/migrate/20150929205301_add_view_dependencies.rb
|
82
82
|
- db/migrate/20151005150022_update_dependency_views.rb
|
83
|
+
- db/migrate/20160512173021_update_view_replace_function.rb
|
83
84
|
- lib/tasks/viewy_tasks.rake
|
84
85
|
- lib/viewy.rb
|
85
86
|
- lib/viewy/acts_as_materialized_view.rb
|
@@ -89,6 +90,7 @@ files:
|
|
89
90
|
- lib/viewy/dependency_management/view_sorter.rb
|
90
91
|
- lib/viewy/dependency_manager.rb
|
91
92
|
- lib/viewy/engine.rb
|
93
|
+
- lib/viewy/event_triggers.rb
|
92
94
|
- lib/viewy/models.rb
|
93
95
|
- lib/viewy/models/materialized_view_dependency.rb
|
94
96
|
- lib/viewy/models/view_dependency.rb
|