robdimarco_rails_sql_views 0.9.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.
- data/CHANGELOG +22 -0
- data/CONTRIB +8 -0
- data/LICENSE +7 -0
- data/README +51 -0
- data/Rakefile +41 -0
- data/TODO +2 -0
- data/init.rb +1 -0
- data/lib/active_record/view.rb +76 -0
- data/lib/core_ext/module.rb +13 -0
- data/lib/rails_sql_views.rb +51 -0
- data/lib/rails_sql_views/connection_adapters/abstract/schema_definitions.rb +63 -0
- data/lib/rails_sql_views/connection_adapters/abstract/schema_statements.rb +81 -0
- data/lib/rails_sql_views/connection_adapters/abstract_adapter.rb +41 -0
- data/lib/rails_sql_views/connection_adapters/mysql2_adapter.rb +62 -0
- data/lib/rails_sql_views/connection_adapters/mysql_adapter.rb +66 -0
- data/lib/rails_sql_views/connection_adapters/oci_adapter.rb +33 -0
- data/lib/rails_sql_views/connection_adapters/oracle_adapter.rb +33 -0
- data/lib/rails_sql_views/connection_adapters/oracleenhanced_adapter.rb +39 -0
- data/lib/rails_sql_views/connection_adapters/oracleenhanced_adapter.rb.orig +72 -0
- data/lib/rails_sql_views/connection_adapters/postgresql_adapter.rb +65 -0
- data/lib/rails_sql_views/connection_adapters/postgresql_adapter.rb.orig +69 -0
- data/lib/rails_sql_views/connection_adapters/sqlite_adapter.rb +66 -0
- data/lib/rails_sql_views/connection_adapters/sqlserver_adapter.rb +43 -0
- data/lib/rails_sql_views/loader.rb +20 -0
- data/lib/rails_sql_views/schema_dumper.rb +113 -0
- data/lib/rails_sql_views/version.rb +9 -0
- data/rails/init.rb +1 -0
- data/test/README +63 -0
- data/test/adapter_test.rb +82 -0
- data/test/connection.example.yml +12 -0
- data/test/connection/native_mysql/connection.rb +32 -0
- data/test/connection/native_mysql/schema.sql +33 -0
- data/test/connection/native_mysql2/connection.rb +32 -0
- data/test/connection/native_mysql2/schema.sql +33 -0
- data/test/connection/native_postgresql/connection.rb +31 -0
- data/test/connection/native_postgresql/schema.sql +33 -0
- data/test/connection/oracle_enhanced/connection.rb +29 -0
- data/test/connection/oracle_enhanced/procedures.sql +15 -0
- data/test/connection/oracle_enhanced/schema.sql +39 -0
- data/test/models/item.rb +4 -0
- data/test/models/person.rb +5 -0
- data/test/models/person2.rb +3 -0
- data/test/models/place.rb +2 -0
- data/test/models/v_person.rb +4 -0
- data/test/models/v_profile.rb +3 -0
- data/test/schema.native_mysql.expected.rb +57 -0
- data/test/schema.native_mysql2.expected.rb +58 -0
- data/test/schema.native_postgresql.expected.rb +51 -0
- data/test/schema.oracle_enhanced.expected.rb +51 -0
- data/test/schema_dumper_test.rb +130 -0
- data/test/test_helper.rb +30 -0
- data/test/view_model_test.rb +63 -0
- data/test/view_operations_test.rb +36 -0
- metadata +246 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
module RailsSqlViews
|
2
|
+
module ConnectionAdapters
|
3
|
+
module Mysql2Adapter
|
4
|
+
def self.included(base)
|
5
|
+
if base.private_method_defined?(:supports_views?) || base.protected_method_defined?(:supports_views?)
|
6
|
+
base.send(:public, :supports_views?)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns true as this adapter supports views.
|
11
|
+
def supports_views?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def base_tables(name = nil) #:nodoc:
|
16
|
+
tables = []
|
17
|
+
execute("SHOW FULL TABLES WHERE TABLE_TYPE='BASE TABLE'").each{|row| tables << row[0]}
|
18
|
+
tables
|
19
|
+
end
|
20
|
+
alias nonview_tables base_tables
|
21
|
+
|
22
|
+
def views(name = nil) #:nodoc:
|
23
|
+
views = []
|
24
|
+
execute("SHOW FULL TABLES WHERE TABLE_TYPE='VIEW'").each{|row| views << row[0]}
|
25
|
+
views
|
26
|
+
end
|
27
|
+
|
28
|
+
def tables_with_views_included(name = nil)
|
29
|
+
nonview_tables(name) + views(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def structure_dump
|
33
|
+
structure = ""
|
34
|
+
base_tables.each do |table|
|
35
|
+
structure += select_one("SHOW CREATE TABLE #{quote_table_name(table)}")["Create Table"] + ";\n\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
views.each do |view|
|
39
|
+
structure += select_one("SHOW CREATE VIEW #{quote_table_name(view)}")["Create View"] + ";\n\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
return structure
|
43
|
+
end
|
44
|
+
|
45
|
+
# Get the view select statement for the specified table.
|
46
|
+
def view_select_statement(view, name=nil)
|
47
|
+
begin
|
48
|
+
row = execute("SHOW CREATE VIEW #{view}", name).each do |row|
|
49
|
+
return convert_statement(row[1]) if row[0] == view
|
50
|
+
end
|
51
|
+
rescue ActiveRecord::StatementInvalid => e
|
52
|
+
raise "No view called #{view} found"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def convert_statement(s)
|
58
|
+
s.gsub!(/.* AS (select .*)/, '\1')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module RailsSqlViews
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MysqlAdapter
|
4
|
+
REQUIRED_METHODS = [:supports_views?]
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
def self.method_added(method)
|
9
|
+
public(method) if REQUIRED_METHODS.include?(method) && !self.public_method_defined?(method)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns true as this adapter supports views.
|
15
|
+
def supports_views?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def base_tables(name = nil) #:nodoc:
|
20
|
+
tables = []
|
21
|
+
execute("SHOW FULL TABLES WHERE TABLE_TYPE='BASE TABLE'").each{|row| tables << row[0]}
|
22
|
+
tables
|
23
|
+
end
|
24
|
+
alias nonview_tables base_tables
|
25
|
+
|
26
|
+
def views(name = nil) #:nodoc:
|
27
|
+
views = []
|
28
|
+
execute("SHOW FULL TABLES WHERE TABLE_TYPE='VIEW'").each{|row| views << row[0]}
|
29
|
+
views
|
30
|
+
end
|
31
|
+
|
32
|
+
def tables_with_views_included(name = nil)
|
33
|
+
nonview_tables(name) + views(name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def structure_dump
|
37
|
+
structure = ""
|
38
|
+
base_tables.each do |table|
|
39
|
+
structure += select_one("SHOW CREATE TABLE #{quote_table_name(table)}")["Create Table"] + ";\n\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
views.each do |view|
|
43
|
+
structure += select_one("SHOW CREATE VIEW #{quote_table_name(view)}")["Create View"] + ";\n\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
return structure
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get the view select statement for the specified table.
|
50
|
+
def view_select_statement(view, name=nil)
|
51
|
+
begin
|
52
|
+
row = execute("SHOW CREATE VIEW #{view}", name).each do |row|
|
53
|
+
return convert_statement(row[1]) if row[0] == view
|
54
|
+
end
|
55
|
+
rescue ActiveRecord::StatementInvalid => e
|
56
|
+
raise "No view called #{view} found"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def convert_statement(s)
|
62
|
+
s.gsub!(/.* AS (select .*)/, '\1')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RailsSqlViews
|
2
|
+
module ConnectionAdapters
|
3
|
+
module OciAdapter
|
4
|
+
# Returns true as this adapter supports views.
|
5
|
+
def supports_views?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def base_tables(name = nil) #:nodoc:
|
10
|
+
tables = []
|
11
|
+
execute("SELECT TABLE_NAME FROM USER_TABLES", name).each { |row| tables << row[0] }
|
12
|
+
tables
|
13
|
+
end
|
14
|
+
alias nonview_tables base_tables
|
15
|
+
|
16
|
+
def views(name = nil) #:nodoc:
|
17
|
+
views = []
|
18
|
+
execute("SELECT VIEW_NAME FROM USER_VIEWS", name).each { |row| views << row[0] }
|
19
|
+
views
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get the view select statement for the specified table.
|
23
|
+
def view_select_statement(view, name=nil)
|
24
|
+
row = execute("SELECT TEXT FROM USER_VIEWS WHERE VIEW_NAME = '#{view}'", name).each do |row|
|
25
|
+
return row[0]
|
26
|
+
end
|
27
|
+
raise "No view called #{view} found"
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RailsSqlViews
|
2
|
+
module ConnectionAdapters
|
3
|
+
module OracleAdapter
|
4
|
+
# Returns true as this adapter supports views.
|
5
|
+
def supports_views?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def base_tables(name = nil) #:nodoc:
|
10
|
+
tables = []
|
11
|
+
execute("SELECT TABLE_NAME FROM USER_TABLES", name).each { |row| tables << row[0] }
|
12
|
+
tables
|
13
|
+
end
|
14
|
+
alias nonview_tables base_tables
|
15
|
+
|
16
|
+
def views(name = nil) #:nodoc:
|
17
|
+
views = []
|
18
|
+
execute("SELECT VIEW_NAME FROM USER_VIEWS", name).each { |row| views << row[0] }
|
19
|
+
views
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get the view select statement for the specified table.
|
23
|
+
def view_select_statement(view, name=nil)
|
24
|
+
row = execute("SELECT TEXT FROM USER_VIEWS WHERE VIEW_NAME = '#{view}'", name).each do |row|
|
25
|
+
return row[0]
|
26
|
+
end
|
27
|
+
raise "No view called #{view} found"
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RailsSqlViews
|
2
|
+
module ConnectionAdapters
|
3
|
+
module OracleEnhancedAdapter
|
4
|
+
# Returns true as this adapter supports views.
|
5
|
+
def supports_views?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def base_tables(name = nil) #:nodoc:
|
10
|
+
tables = []
|
11
|
+
cursor = execute("SELECT TABLE_NAME FROM USER_TABLES", name)
|
12
|
+
while row = cursor.fetch
|
13
|
+
tables << row[0]
|
14
|
+
end
|
15
|
+
tables
|
16
|
+
end
|
17
|
+
alias nonview_tables base_tables
|
18
|
+
|
19
|
+
def views(name = nil) #:nodoc:
|
20
|
+
views = []
|
21
|
+
cursor = execute("SELECT VIEW_NAME FROM USER_VIEWS", name)
|
22
|
+
while row = cursor.fetch
|
23
|
+
views << row[0]
|
24
|
+
end
|
25
|
+
views
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get the view select statement for the specified table.
|
29
|
+
def view_select_statement(view, name=nil)
|
30
|
+
cursor = execute("SELECT TEXT FROM USER_VIEWS WHERE VIEW_NAME = '#{view}'", name)
|
31
|
+
if row = cursor.fetch
|
32
|
+
return row[0]
|
33
|
+
else
|
34
|
+
raise "No view called #{view} found"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module RailsSqlViews
|
2
|
+
module ConnectionAdapters
|
3
|
+
module OracleEnhancedAdapter
|
4
|
+
<<<<<<< HEAD
|
5
|
+
def self.included(base)
|
6
|
+
base.alias_method_chain :tables, :views_included
|
7
|
+
end
|
8
|
+
=======
|
9
|
+
>>>>>>> Add support for oracle_enhanced adapter. Don't alias tables in PostgreSQL adapter if it's already been aliased.
|
10
|
+
# Returns true as this adapter supports views.
|
11
|
+
def supports_views?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
<<<<<<< HEAD
|
16
|
+
def tables_with_views_included(name = nil)
|
17
|
+
tables = []
|
18
|
+
sql = " SELECT TABLE_NAME FROM USER_TABLES
|
19
|
+
UNION
|
20
|
+
SELECT VIEW_NAME AS TABLE_NAME FROM USER_VIEWS"
|
21
|
+
cursor = execute(sql, name)
|
22
|
+
while row = cursor.fetch
|
23
|
+
tables << row[0].downcase
|
24
|
+
end
|
25
|
+
tables
|
26
|
+
end
|
27
|
+
|
28
|
+
=======
|
29
|
+
>>>>>>> Add support for oracle_enhanced adapter. Don't alias tables in PostgreSQL adapter if it's already been aliased.
|
30
|
+
def base_tables(name = nil) #:nodoc:
|
31
|
+
tables = []
|
32
|
+
cursor = execute("SELECT TABLE_NAME FROM USER_TABLES", name)
|
33
|
+
while row = cursor.fetch
|
34
|
+
<<<<<<< HEAD
|
35
|
+
tables << row[0].downcase
|
36
|
+
=======
|
37
|
+
tables << row[0]
|
38
|
+
>>>>>>> Add support for oracle_enhanced adapter. Don't alias tables in PostgreSQL adapter if it's already been aliased.
|
39
|
+
end
|
40
|
+
tables
|
41
|
+
end
|
42
|
+
alias nonview_tables base_tables
|
43
|
+
|
44
|
+
def views(name = nil) #:nodoc:
|
45
|
+
views = []
|
46
|
+
cursor = execute("SELECT VIEW_NAME FROM USER_VIEWS", name)
|
47
|
+
while row = cursor.fetch
|
48
|
+
<<<<<<< HEAD
|
49
|
+
views << row[0].downcase
|
50
|
+
=======
|
51
|
+
views << row[0]
|
52
|
+
>>>>>>> Add support for oracle_enhanced adapter. Don't alias tables in PostgreSQL adapter if it's already been aliased.
|
53
|
+
end
|
54
|
+
views
|
55
|
+
end
|
56
|
+
|
57
|
+
# Get the view select statement for the specified table.
|
58
|
+
def view_select_statement(view, name=nil)
|
59
|
+
<<<<<<< HEAD
|
60
|
+
view.upcase!
|
61
|
+
=======
|
62
|
+
>>>>>>> Add support for oracle_enhanced adapter. Don't alias tables in PostgreSQL adapter if it's already been aliased.
|
63
|
+
cursor = execute("SELECT TEXT FROM USER_VIEWS WHERE VIEW_NAME = '#{view}'", name)
|
64
|
+
if row = cursor.fetch
|
65
|
+
return row[0]
|
66
|
+
else
|
67
|
+
raise "No view called #{view} found"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module RailsSqlViews
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQLAdapter
|
4
|
+
def self.included(base)
|
5
|
+
base.alias_method_chain :tables, :views_included unless method_defined?(:tables_with_views_included)
|
6
|
+
end
|
7
|
+
# Returns true as this adapter supports views.
|
8
|
+
def supports_views?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def tables_with_views_included(name = nil)
|
13
|
+
q = <<-SQL
|
14
|
+
SELECT table_name, table_type
|
15
|
+
FROM information_schema.tables
|
16
|
+
WHERE table_schema IN (#{schemas})
|
17
|
+
AND table_type IN ('BASE TABLE', 'VIEW')
|
18
|
+
SQL
|
19
|
+
|
20
|
+
query(q, name).map { |row| row[0] }
|
21
|
+
end
|
22
|
+
|
23
|
+
def base_tables(name = nil)
|
24
|
+
q = <<-SQL
|
25
|
+
SELECT table_name, table_type
|
26
|
+
FROM information_schema.tables
|
27
|
+
WHERE table_schema IN (#{schemas})
|
28
|
+
AND table_type = 'BASE TABLE'
|
29
|
+
SQL
|
30
|
+
|
31
|
+
query(q, name).map { |row| row[0] }
|
32
|
+
end
|
33
|
+
alias nonview_tables base_tables
|
34
|
+
|
35
|
+
def views(name = nil) #:nodoc:
|
36
|
+
q = <<-SQL
|
37
|
+
SELECT table_name, table_type
|
38
|
+
FROM information_schema.tables
|
39
|
+
WHERE table_schema IN (#{schemas})
|
40
|
+
AND table_type = 'VIEW'
|
41
|
+
SQL
|
42
|
+
|
43
|
+
query(q, name).map { |row| row[0] }
|
44
|
+
end
|
45
|
+
|
46
|
+
def view_select_statement(view, name = nil)
|
47
|
+
q = <<-SQL
|
48
|
+
SELECT view_definition
|
49
|
+
FROM information_schema.views
|
50
|
+
WHERE table_catalog = (SELECT catalog_name FROM information_schema.information_schema_catalog_name)
|
51
|
+
AND table_schema IN (#{schemas})
|
52
|
+
AND table_name = '#{view}'
|
53
|
+
SQL
|
54
|
+
|
55
|
+
select_value(q, name) or raise "No view called #{view} found"
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def schemas
|
61
|
+
schema_search_path.split(/,/).map { |p| quote(p) }.join(',')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module RailsSqlViews
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQLAdapter
|
4
|
+
def self.included(base)
|
5
|
+
<<<<<<< HEAD
|
6
|
+
base.alias_method_chain :tables, :views_included unless method_defined?(:tables_with_views_included)
|
7
|
+
=======
|
8
|
+
base.alias_method_chain :tables, :views_included
|
9
|
+
>>>>>>> Make tests pass again for PostgreSQL and MySQL adapters.
|
10
|
+
end
|
11
|
+
# Returns true as this adapter supports views.
|
12
|
+
def supports_views?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def tables_with_views_included(name = nil)
|
17
|
+
q = <<-SQL
|
18
|
+
SELECT table_name, table_type
|
19
|
+
FROM information_schema.tables
|
20
|
+
WHERE table_schema IN (#{schemas})
|
21
|
+
AND table_type IN ('BASE TABLE', 'VIEW')
|
22
|
+
SQL
|
23
|
+
|
24
|
+
query(q, name).map { |row| row[0] }
|
25
|
+
end
|
26
|
+
|
27
|
+
def base_tables(name = nil)
|
28
|
+
q = <<-SQL
|
29
|
+
SELECT table_name, table_type
|
30
|
+
FROM information_schema.tables
|
31
|
+
WHERE table_schema IN (#{schemas})
|
32
|
+
AND table_type = 'BASE TABLE'
|
33
|
+
SQL
|
34
|
+
|
35
|
+
query(q, name).map { |row| row[0] }
|
36
|
+
end
|
37
|
+
alias nonview_tables base_tables
|
38
|
+
|
39
|
+
def views(name = nil) #:nodoc:
|
40
|
+
q = <<-SQL
|
41
|
+
SELECT table_name, table_type
|
42
|
+
FROM information_schema.tables
|
43
|
+
WHERE table_schema IN (#{schemas})
|
44
|
+
AND table_type = 'VIEW'
|
45
|
+
SQL
|
46
|
+
|
47
|
+
query(q, name).map { |row| row[0] }
|
48
|
+
end
|
49
|
+
|
50
|
+
def view_select_statement(view, name = nil)
|
51
|
+
q = <<-SQL
|
52
|
+
SELECT view_definition
|
53
|
+
FROM information_schema.views
|
54
|
+
WHERE table_catalog = (SELECT catalog_name FROM information_schema.information_schema_catalog_name)
|
55
|
+
AND table_schema IN (#{schemas})
|
56
|
+
AND table_name = '#{view}'
|
57
|
+
SQL
|
58
|
+
|
59
|
+
select_value(q, name) or raise "No view called #{view} found"
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def schemas
|
65
|
+
schema_search_path.split(/,/).map { |p| quote(p) }.join(',')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|