molo 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/Molo.gemspec +56 -2
  2. data/README.markdown +31 -7
  3. data/Rakefile +1 -1
  4. data/VERSION +1 -1
  5. data/lib/tasks/molo.rb +9 -3
  6. data/vendor/rails_sql_views/.gitignore +3 -0
  7. data/vendor/rails_sql_views/CHANGELOG +22 -0
  8. data/vendor/rails_sql_views/CONTRIB +8 -0
  9. data/vendor/rails_sql_views/LICENSE +7 -0
  10. data/vendor/rails_sql_views/README +51 -0
  11. data/vendor/rails_sql_views/Rakefile +74 -0
  12. data/vendor/rails_sql_views/TODO +2 -0
  13. data/vendor/rails_sql_views/VERSION +1 -0
  14. data/vendor/rails_sql_views/init.rb +1 -0
  15. data/vendor/rails_sql_views/lib/active_record/view.rb +76 -0
  16. data/vendor/rails_sql_views/lib/core_ext/module.rb +13 -0
  17. data/vendor/rails_sql_views/lib/rails_sql_views.rb +47 -0
  18. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/abstract/schema_definitions.rb +63 -0
  19. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/abstract/schema_statements.rb +79 -0
  20. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/abstract_adapter.rb +41 -0
  21. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/mysql2_adapter.rb +62 -0
  22. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/mysql_adapter.rb +62 -0
  23. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/oci_adapter.rb +33 -0
  24. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/oracle_adapter.rb +33 -0
  25. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/oracleenhanced_adapter.rb +39 -0
  26. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/oracleenhanced_adapter.rb.orig +72 -0
  27. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/postgresql_adapter.rb +65 -0
  28. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/postgresql_adapter.rb.orig +69 -0
  29. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/sqlite_adapter.rb +66 -0
  30. data/vendor/rails_sql_views/lib/rails_sql_views/connection_adapters/sqlserver_adapter.rb +43 -0
  31. data/vendor/rails_sql_views/lib/rails_sql_views/loader.rb +18 -0
  32. data/vendor/rails_sql_views/lib/rails_sql_views/schema_dumper.rb +112 -0
  33. data/vendor/rails_sql_views/lib/rails_sql_views/version.rb +9 -0
  34. data/vendor/rails_sql_views/rails/init.rb +1 -0
  35. data/vendor/rails_sql_views/rails_sql_views.gemspec +81 -0
  36. data/vendor/rails_sql_views/test/.gitignore +1 -0
  37. data/vendor/rails_sql_views/test/README +63 -0
  38. data/vendor/rails_sql_views/test/adapter_test.rb +82 -0
  39. data/vendor/rails_sql_views/test/connection.example.yml +12 -0
  40. data/vendor/rails_sql_views/test/connection/native_mysql/connection.rb +32 -0
  41. data/vendor/rails_sql_views/test/connection/native_mysql/schema.sql +33 -0
  42. data/vendor/rails_sql_views/test/connection/native_postgresql/connection.rb +31 -0
  43. data/vendor/rails_sql_views/test/connection/native_postgresql/schema.sql +33 -0
  44. data/vendor/rails_sql_views/test/connection/oracle_enhanced/connection.rb +29 -0
  45. data/vendor/rails_sql_views/test/connection/oracle_enhanced/procedures.sql +15 -0
  46. data/vendor/rails_sql_views/test/connection/oracle_enhanced/schema.sql +39 -0
  47. data/vendor/rails_sql_views/test/models/item.rb +4 -0
  48. data/vendor/rails_sql_views/test/models/person.rb +5 -0
  49. data/vendor/rails_sql_views/test/models/person2.rb +3 -0
  50. data/vendor/rails_sql_views/test/models/place.rb +2 -0
  51. data/vendor/rails_sql_views/test/models/v_person.rb +4 -0
  52. data/vendor/rails_sql_views/test/models/v_profile.rb +3 -0
  53. data/vendor/rails_sql_views/test/schema.native_mysql.expected.rb +51 -0
  54. data/vendor/rails_sql_views/test/schema.native_postgresql.expected.rb +51 -0
  55. data/vendor/rails_sql_views/test/schema.oracle_enhanced.expected.rb +51 -0
  56. data/vendor/rails_sql_views/test/schema_dumper_test.rb +117 -0
  57. data/vendor/rails_sql_views/test/test_helper.rb +30 -0
  58. data/vendor/rails_sql_views/test/view_model_test.rb +63 -0
  59. data/vendor/rails_sql_views/test/view_operations_test.rb +36 -0
  60. data/vendor/yaml_db/lib/serialization_helper.rb +15 -10
  61. metadata +58 -4
@@ -0,0 +1,13 @@
1
+ # This is required for 1.1.6 support
2
+ unless Module.respond_to?(:alias_method_chain)
3
+ class Module
4
+ def alias_method_chain(target, feature)
5
+ # Strip out punctuation on predicates or bang methods since
6
+ # e.g. target?_without_feature is not a valid method name.
7
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
8
+ yield(aliased_target, punctuation) if block_given?
9
+ alias_method "#{aliased_target}_without_#{feature}#{punctuation}", target
10
+ alias_method target, "#{aliased_target}_with_#{feature}#{punctuation}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ #--
2
+ # Copyright (c) 2006 Anthony Eden
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ $:.unshift(File.dirname(__FILE__))
25
+
26
+ require 'active_record'
27
+
28
+ require 'core_ext/module'
29
+
30
+ require 'rails_sql_views/connection_adapters/abstract/schema_definitions'
31
+ require 'rails_sql_views/connection_adapters/abstract/schema_statements'
32
+ require 'rails_sql_views/connection_adapters/abstract_adapter'
33
+ require 'rails_sql_views/schema_dumper'
34
+ require 'rails_sql_views/loader'
35
+
36
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
37
+ include RailsSqlViews::ConnectionAdapters::SchemaStatements
38
+ def self.inherited(sub)
39
+ RailsSqlViews::Loader.load_extensions
40
+ end
41
+ end
42
+
43
+ ActiveRecord::SchemaDumper.class_eval do
44
+ include RailsSqlViews::SchemaDumper
45
+ end
46
+
47
+ RailsSqlViews::Loader.load_extensions
@@ -0,0 +1,63 @@
1
+ module RailsSqlViews
2
+ module ConnectionAdapters #:nodoc:
3
+ # Abstract definition of a View
4
+ class ViewDefinition
5
+ attr_accessor :columns, :select_query
6
+
7
+ def initialize(base, select_query)
8
+ @columns = []
9
+ @base = base
10
+ @select_query = select_query
11
+ end
12
+
13
+ def column(name)
14
+ column = name.to_s
15
+ @columns << column unless @columns.include? column
16
+ self
17
+ end
18
+
19
+ def to_sql
20
+ @columns.collect { |c| @base.quote_column_name(c) } * ', '
21
+ end
22
+
23
+ end
24
+
25
+ class MappingDefinition
26
+
27
+ # Generates a hash of the form :old_column => :new_column
28
+ # Initially, it'll map column names to themselves.
29
+ # use map_column to modify the list.
30
+ def initialize(columns)
31
+ @columns = columns
32
+ @map = Hash.new()
33
+ columns.each do |c|
34
+ @map[c] = c
35
+ end
36
+
37
+ end
38
+
39
+ # Create a mapping from an old column name to a new one.
40
+ # If the new name is nil, specify that the old column shouldn't
41
+ # appear in this new view.
42
+ def map_column(old_name, new_name)
43
+ unless @map.include?(old_name)
44
+ raise ActiveRecord::ActiveRecordError, "column #{old_name} not found, can't be mapped"
45
+ end
46
+ if new_name.nil?
47
+ @map.delete old_name
48
+ @columns.delete old_name
49
+ else
50
+ @map[old_name] = new_name
51
+ end
52
+ end
53
+
54
+ def select_cols
55
+ @columns
56
+ end
57
+
58
+ def view_cols
59
+ @columns.map { |c| @map[c] }
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,79 @@
1
+ module RailsSqlViews
2
+ module ConnectionAdapters # :nodoc:
3
+ module SchemaStatements
4
+ def self.included(base)
5
+ base.alias_method_chain :drop_table, :cascade
6
+ end
7
+
8
+ # Create a view.
9
+ # The +options+ hash can include the following keys:
10
+ # [<tt>:check_option</tt>]
11
+ # Specify restrictions for inserts or updates in updatable views. ANSI SQL 92 defines two check option
12
+ # values: CASCADED and LOCAL. See your database documentation for allowed values.
13
+ def create_view(name, select_query, options={})
14
+ if supports_views?
15
+ view_definition = ViewDefinition.new(self, select_query)
16
+
17
+ if block_given?
18
+ yield view_definition
19
+ end
20
+
21
+ if options[:force]
22
+ drop_view(name) rescue nil
23
+ end
24
+
25
+ create_sql = "CREATE VIEW "
26
+ create_sql << "#{quote_table_name(name)} "
27
+ if supports_view_columns_definition? && !view_definition.to_sql.blank?
28
+ create_sql << "("
29
+ create_sql << view_definition.to_sql
30
+ create_sql << ") "
31
+ end
32
+ create_sql << "AS #{view_definition.select_query}"
33
+ create_sql << " WITH #{options[:check_option]} CHECK OPTION" if options[:check_option]
34
+ execute create_sql
35
+ end
36
+ end
37
+
38
+ # Also creates a view, with the specific purpose of remapping column names
39
+ # to make non-ActiveRecord tables friendly with the naming
40
+ # conventions, while maintaining legacy app compatibility.
41
+ def create_mapping_view(old_name, new_name, options = {})
42
+ return unless supports_views?
43
+
44
+ col_names = columns(old_name).collect { |col| col.name.to_sym }
45
+ mapper = MappingDefinition.new(col_names)
46
+
47
+ yield mapper
48
+
49
+ if options[:force]
50
+ drop_view(new_name) rescue nil
51
+ end
52
+
53
+ view_sql = "CREATE VIEW #{new_name} "
54
+ if supports_view_columns_definition?
55
+ view_sql << "(#{mapper.view_cols.collect { |c| quote_column_name(c) }.join(', ')}) "
56
+ end
57
+ view_sql << "AS SELECT #{mapper.select_cols.collect { |c| quote_column_name(c) }.join(', ')} FROM #{old_name}"
58
+ execute view_sql
59
+ end
60
+
61
+ def drop_table_with_cascade(table_name, options = {})
62
+ execute "DROP TABLE #{quote_table_name(table_name)} CASCADE"
63
+ end
64
+
65
+ # Drop a view.
66
+ # The +options+ hash can include the following keys:
67
+ # [<tt>:drop_behavior</tt>]
68
+ # Specify the drop behavior. ANSI SQL 92 defines two drop behaviors, CASCADE and RESTRICT. See your
69
+ # database documentation to determine what drop behaviors are available.
70
+ def drop_view(name, options={})
71
+ if supports_views?
72
+ drop_sql = "DROP VIEW #{quote_table_name(name)}"
73
+ drop_sql << " #{options[:drop_behavior]}" if options[:drop_behavior]
74
+ execute drop_sql
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,41 @@
1
+ module RailsSqlViews
2
+ module ConnectionAdapters
3
+ module AbstractAdapter
4
+ def self.included(base)
5
+ base.alias_method_chain :disable_referential_integrity, :views_excluded
6
+ end
7
+
8
+ # Subclasses should override and return true if they support views.
9
+ def supports_views?
10
+ return false
11
+ end
12
+
13
+ # Subclasses should override and return false if they don't support CASCADE
14
+ def supports_drop_table_cascade?
15
+ return true
16
+ end
17
+
18
+ def disable_referential_integrity_with_views_excluded(&block)
19
+ self.class.send(:alias_method, :original_tables_method, :tables)
20
+ self.class.send(:alias_method, :tables, :base_tables)
21
+ disable_referential_integrity_without_views_excluded(&block)
22
+ ensure
23
+ self.class.send(:alias_method, :tables, :original_tables_method)
24
+ end
25
+
26
+ def supports_view_columns_definition?
27
+ true
28
+ end
29
+
30
+ # Get a list of all views for the current database
31
+ def views(name = nil)
32
+ raise NotImplementedError, "views is an abstract method"
33
+ end
34
+
35
+ # Get the select statement for the specified view
36
+ def view_select_statement(view, name=nil)
37
+ raise NotImplementedError, "view_select_statement is an abstract method"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -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?)
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,62 @@
1
+ module RailsSqlViews
2
+ module ConnectionAdapters
3
+ module MysqlAdapter
4
+ def self.included(base)
5
+ if base.private_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,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