viewy 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|