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.
Files changed (54) hide show
  1. data/CHANGELOG +22 -0
  2. data/CONTRIB +8 -0
  3. data/LICENSE +7 -0
  4. data/README +51 -0
  5. data/Rakefile +41 -0
  6. data/TODO +2 -0
  7. data/init.rb +1 -0
  8. data/lib/active_record/view.rb +76 -0
  9. data/lib/core_ext/module.rb +13 -0
  10. data/lib/rails_sql_views.rb +51 -0
  11. data/lib/rails_sql_views/connection_adapters/abstract/schema_definitions.rb +63 -0
  12. data/lib/rails_sql_views/connection_adapters/abstract/schema_statements.rb +81 -0
  13. data/lib/rails_sql_views/connection_adapters/abstract_adapter.rb +41 -0
  14. data/lib/rails_sql_views/connection_adapters/mysql2_adapter.rb +62 -0
  15. data/lib/rails_sql_views/connection_adapters/mysql_adapter.rb +66 -0
  16. data/lib/rails_sql_views/connection_adapters/oci_adapter.rb +33 -0
  17. data/lib/rails_sql_views/connection_adapters/oracle_adapter.rb +33 -0
  18. data/lib/rails_sql_views/connection_adapters/oracleenhanced_adapter.rb +39 -0
  19. data/lib/rails_sql_views/connection_adapters/oracleenhanced_adapter.rb.orig +72 -0
  20. data/lib/rails_sql_views/connection_adapters/postgresql_adapter.rb +65 -0
  21. data/lib/rails_sql_views/connection_adapters/postgresql_adapter.rb.orig +69 -0
  22. data/lib/rails_sql_views/connection_adapters/sqlite_adapter.rb +66 -0
  23. data/lib/rails_sql_views/connection_adapters/sqlserver_adapter.rb +43 -0
  24. data/lib/rails_sql_views/loader.rb +20 -0
  25. data/lib/rails_sql_views/schema_dumper.rb +113 -0
  26. data/lib/rails_sql_views/version.rb +9 -0
  27. data/rails/init.rb +1 -0
  28. data/test/README +63 -0
  29. data/test/adapter_test.rb +82 -0
  30. data/test/connection.example.yml +12 -0
  31. data/test/connection/native_mysql/connection.rb +32 -0
  32. data/test/connection/native_mysql/schema.sql +33 -0
  33. data/test/connection/native_mysql2/connection.rb +32 -0
  34. data/test/connection/native_mysql2/schema.sql +33 -0
  35. data/test/connection/native_postgresql/connection.rb +31 -0
  36. data/test/connection/native_postgresql/schema.sql +33 -0
  37. data/test/connection/oracle_enhanced/connection.rb +29 -0
  38. data/test/connection/oracle_enhanced/procedures.sql +15 -0
  39. data/test/connection/oracle_enhanced/schema.sql +39 -0
  40. data/test/models/item.rb +4 -0
  41. data/test/models/person.rb +5 -0
  42. data/test/models/person2.rb +3 -0
  43. data/test/models/place.rb +2 -0
  44. data/test/models/v_person.rb +4 -0
  45. data/test/models/v_profile.rb +3 -0
  46. data/test/schema.native_mysql.expected.rb +57 -0
  47. data/test/schema.native_mysql2.expected.rb +58 -0
  48. data/test/schema.native_postgresql.expected.rb +51 -0
  49. data/test/schema.oracle_enhanced.expected.rb +51 -0
  50. data/test/schema_dumper_test.rb +130 -0
  51. data/test/test_helper.rb +30 -0
  52. data/test/view_model_test.rb +63 -0
  53. data/test/view_operations_test.rb +36 -0
  54. 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