rails_sql_views4 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +121 -0
  5. data/lib/active_record/view.rb +80 -0
  6. data/lib/core_ext/module.rb +13 -0
  7. data/lib/rails_sql_views4/connection_adapters/abstract/schema_definitions.rb +63 -0
  8. data/lib/rails_sql_views4/connection_adapters/abstract/schema_statements.rb +85 -0
  9. data/lib/rails_sql_views4/connection_adapters/abstract_adapter.rb +41 -0
  10. data/lib/rails_sql_views4/connection_adapters/mysql2_adapter.rb +66 -0
  11. data/lib/rails_sql_views4/connection_adapters/mysql_adapter.rb +66 -0
  12. data/lib/rails_sql_views4/connection_adapters/oci_adapter.rb +33 -0
  13. data/lib/rails_sql_views4/connection_adapters/oracle_adapter.rb +33 -0
  14. data/lib/rails_sql_views4/connection_adapters/oracleenhanced_adapter.rb +39 -0
  15. data/lib/rails_sql_views4/connection_adapters/oracleenhanced_adapter.rb.orig +72 -0
  16. data/lib/rails_sql_views4/connection_adapters/postgresql_adapter.rb +69 -0
  17. data/lib/rails_sql_views4/connection_adapters/postgresql_adapter.rb.orig +69 -0
  18. data/lib/rails_sql_views4/connection_adapters/sqlite3_adapter.rb +68 -0
  19. data/lib/rails_sql_views4/connection_adapters/sqlite_adapter.rb +68 -0
  20. data/lib/rails_sql_views4/connection_adapters/sqlserver_adapter.rb +43 -0
  21. data/lib/rails_sql_views4/loader.rb +18 -0
  22. data/lib/rails_sql_views4/schema_dumper.rb +114 -0
  23. data/lib/rails_sql_views4/version.rb +3 -0
  24. data/lib/rails_sql_views4.rb +28 -0
  25. data/lib/tasks/rails_sql_views4_tasks.rake +4 -0
  26. data/test/README.NOT_UP_TO_DATE +63 -0
  27. data/test/adapter_test.rb +93 -0
  28. data/test/connection/native_mysql/connection.rb +32 -0
  29. data/test/connection/native_mysql/schema.sql +34 -0
  30. data/test/connection/native_postgresql/connection.rb +31 -0
  31. data/test/connection/native_postgresql/schema.sql +33 -0
  32. data/test/connection/oracle_enhanced/connection.rb +29 -0
  33. data/test/connection/oracle_enhanced/procedures.sql +15 -0
  34. data/test/connection/oracle_enhanced/schema.sql +39 -0
  35. data/test/connection.example.yml +12 -0
  36. data/test/dummy/README.rdoc +28 -0
  37. data/test/dummy/Rakefile +6 -0
  38. data/test/dummy/app/assets/javascripts/application.js +13 -0
  39. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  40. data/test/dummy/app/controllers/application_controller.rb +5 -0
  41. data/test/dummy/app/helpers/application_helper.rb +2 -0
  42. data/test/dummy/app/models/item.rb +4 -0
  43. data/test/dummy/app/models/person.rb +5 -0
  44. data/test/dummy/app/models/person2.rb +4 -0
  45. data/test/dummy/app/models/place.rb +2 -0
  46. data/test/dummy/app/models/v_person.rb +8 -0
  47. data/test/dummy/app/models/v_profile.rb +3 -0
  48. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  49. data/test/dummy/bin/bundle +3 -0
  50. data/test/dummy/bin/rails +4 -0
  51. data/test/dummy/bin/rake +4 -0
  52. data/test/dummy/config/application.rb +23 -0
  53. data/test/dummy/config/boot.rb +5 -0
  54. data/test/dummy/config/database.yml +25 -0
  55. data/test/dummy/config/environment.rb +5 -0
  56. data/test/dummy/config/environments/development.rb +37 -0
  57. data/test/dummy/config/environments/production.rb +78 -0
  58. data/test/dummy/config/environments/test.rb +39 -0
  59. data/test/dummy/config/initializers/assets.rb +8 -0
  60. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  61. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  62. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  63. data/test/dummy/config/initializers/inflections.rb +16 -0
  64. data/test/dummy/config/initializers/mime_types.rb +4 -0
  65. data/test/dummy/config/initializers/session_store.rb +3 -0
  66. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  67. data/test/dummy/config/locales/en.yml +23 -0
  68. data/test/dummy/config/routes.rb +56 -0
  69. data/test/dummy/config/secrets.yml +22 -0
  70. data/test/dummy/config.ru +4 -0
  71. data/test/dummy/db/development.sqlite3 +0 -0
  72. data/test/dummy/db/migrate/20141228200436_create_people.rb +10 -0
  73. data/test/dummy/db/migrate/20141228200437_create_people2.rb +11 -0
  74. data/test/dummy/db/migrate/20141228200438_create_places.rb +12 -0
  75. data/test/dummy/db/migrate/20141228200439_create_items.rb +8 -0
  76. data/test/dummy/db/migrate/20141228200440_create_items_people.rb +9 -0
  77. data/test/dummy/db/schema.rb +53 -0
  78. data/test/dummy/db/test.sqlite3 +0 -0
  79. data/test/dummy/log/development.log +439 -0
  80. data/test/dummy/log/test.log +29320 -0
  81. data/test/dummy/public/404.html +67 -0
  82. data/test/dummy/public/422.html +67 -0
  83. data/test/dummy/public/500.html +66 -0
  84. data/test/dummy/public/favicon.ico +0 -0
  85. data/test/dummy/test/fixtures/persons.yml +7 -0
  86. data/test/dummy/test/models/person_test.rb +7 -0
  87. data/test/rails_sql_views4_test.rb +11 -0
  88. data/test/schema.native_mysql.expected.rb +51 -0
  89. data/test/schema.native_postgresql.expected.rb +51 -0
  90. data/test/schema.native_postgresql.out.rb +69 -0
  91. data/test/schema.oracle_enhanced.expected.rb +51 -0
  92. data/test/schema_dumper_test.rb +134 -0
  93. data/test/test_helper.rb +41 -0
  94. data/test/test_helper.rb.old +30 -0
  95. data/test/view_model_test.rb +68 -0
  96. data/test/view_operations_test.rb +50 -0
  97. metadata +225 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 544ca00235098c24ee35405ec3e987b4f5ab6bcd
4
+ data.tar.gz: ee2305432c09bd0d162a5f1cd22604449074bc99
5
+ SHA512:
6
+ metadata.gz: 628f2d45cc82e7ed647096a9a0f20748e4a82d7d5995c846bea5e3f7991ac4c7126d29e530d4e3806625d01a967d683e129fee8bb00e9f09420c0460343099aa
7
+ data.tar.gz: 69e04f6f5de2f4c7ae9186bb5e7b01e46da7c1bfafa052506a6412eab287534e1f355502f6d7d34a769495f1f0cd5c20f39705fddc672ba9021087fd07294202
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = RailsSqlViews4
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,121 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Citier4'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+ Bundler::GemHelper.install_tasks
20
+
21
+ require 'rake/testtask'
22
+
23
+ Rake::TestTask.new(:test) do |t|
24
+ t.libs << 'lib'
25
+ t.libs << 'test'
26
+ t.pattern = 'test/**/*_test.rb'
27
+ t.verbose = false
28
+ end
29
+
30
+
31
+ task default: :test
32
+
33
+ # old rakefile
34
+
35
+ require 'rake'
36
+ require 'rake/testtask'
37
+ # TODO
38
+ # ERROR: 'rake/rdoctask' is obsolete and no longer supported. Use 'rdoc/task' (available in RDoc 2.4.2+) instead.
39
+ # require 'rake/rdoctask'
40
+ require 'rdoc/task'
41
+
42
+ require 'rake/packagetask'
43
+
44
+ # TODO
45
+ # ERROR: 'rake/gempackagetask' is obsolete and no longer supported. Use 'rubygems/package_task' instead.
46
+ # require 'rake/gempackagetask'
47
+ require 'rubygems/package_task'
48
+
49
+ # require File.join(File.dirname(__FILE__), 'lib/rails_sql_views', 'version')
50
+ require File.join(File.dirname(__FILE__), 'lib/rails_sql_views4', 'version')
51
+
52
+ PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
53
+ PKG_NAME = 'rails_sql_views'
54
+ # PKG_VERSION = RailsSqlViews4::VERSION::STRING + PKG_BUILD
55
+ PKG_VERSION = RailsSqlViews4::VERSION + PKG_BUILD
56
+
57
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
58
+ PKG_DESTINATION = ENV["PKG_DESTINATION"] || "../#{PKG_NAME}"
59
+
60
+ RELEASE_NAME = "REL #{PKG_VERSION}"
61
+
62
+ RUBY_FORGE_PROJECT = "activewarehouse"
63
+ RUBY_FORGE_USER = "aeden"
64
+
65
+ desc 'Default: run unit tests.'
66
+ task :default => :test
67
+
68
+ desc 'Test the library.'
69
+ Rake::TestTask.new(:test) do |t|
70
+ t.libs << 'lib'
71
+ t.pattern = 'test/**/*_test.rb'
72
+ t.verbose = true
73
+ end
74
+
75
+ namespace :rcov do
76
+ desc 'Measures test coverage'
77
+ task :test do
78
+ rm_f 'coverage.data'
79
+ mkdir 'coverage' unless File.exist?('coverage')
80
+ rcov = "rcov --aggregate coverage.data --text-summary -Ilib"
81
+ system("#{rcov} test/*_test.rb test/**/*_test.rb")
82
+ system("open coverage/index.html") if PLATFORM['darwin']
83
+ end
84
+ end
85
+
86
+ # TODO
87
+ #'rake/rdoctask' is obsolete and no longer supported. Use 'rdoc/task' (available in RDoc 2.4.2+) instead.
88
+ #desc 'Generate documentation library.'
89
+ #Rake::RDocTask.new(:rdoc) do |rdoc|
90
+ # rdoc.rdoc_dir = 'rdoc'
91
+ # rdoc.title = 'Rails SQL Views'
92
+ # rdoc.options << '--line-numbers' << '--inline-source'
93
+ # rdoc.rdoc_files.include('README')
94
+ # rdoc.rdoc_files.include('lib/**/*.rb')
95
+ #end
96
+
97
+ begin
98
+ require 'jeweler'
99
+ Jeweler::Tasks.new do |s|
100
+ s.name = "rails_sql_views"
101
+ s.summary = "Library which adds SQL Views to ActiveRecord."
102
+ s.email = "josh@technicalpickles.com"
103
+ s.homepage = "http://activewarehouse.rubyforge.org/rails_sql_views"
104
+ s.description = "Adds support for using SQL views within ActiveRecord"
105
+ s.authors = ["Anthony Eden"]
106
+ s.files = FileList[
107
+ "CHANGELOG",
108
+ "README",
109
+ "Rakefile",
110
+ "{bin,lib}/**/*"
111
+ ]
112
+ s.add_dependency 'activerecord'
113
+ end
114
+ rescue LoadError
115
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
116
+ end
117
+
118
+ desc "Publish the API documentation"
119
+ task :pdoc => [:rdoc] do
120
+ Rake::SshDirPublisher.new("aeden@rubyforge.org", "/var/www/gforge-projects/activewarehouse/rails_sql_views/rdoc", "rdoc").upload
121
+ end
@@ -0,0 +1,80 @@
1
+
2
+ # A base class for database views.
3
+ # It is primarily useful for views that are centered around a single table/model.
4
+ module ActiveRecord # :nodoc:
5
+ class View < Base
6
+ self.abstract_class = true
7
+
8
+ def readonly?
9
+ true
10
+ end
11
+
12
+ class << self
13
+ # Clones all applicable associations from +model+ to this view
14
+ # and provides an instance method
15
+ # <tt>to_<em>model</em></tt>
16
+ # that casts a view object to an object of the kind view is
17
+ # based on. This latter object may be missing attributes; to fill
18
+ # them in, call #reload.
19
+ def based_on(model)
20
+ define_method("to_#{model.name.demodulize.underscore}") do
21
+ becomes(model)
22
+ end
23
+
24
+ model.reflect_on_all_associations.each do |assoc|
25
+ clone_association(model, assoc)
26
+ end
27
+ end
28
+
29
+ # Clone one or more associations from +model+ to this view class.
30
+ #
31
+ # NOTE: Currently only <tt>belongs_to</tt>, <tt>has_many</tt> (withouth
32
+ # <tt>:through</tt>), and <tt>has_and_belongs_to_many</tt> associations
33
+ # are supported.
34
+ def clone_association(model, *associations)
35
+ associations.each do |association|
36
+ r = case association
37
+ when String, Symbol
38
+ model.reflect_on_association(association.to_sym)
39
+ when ActiveRecord::Reflection::AssociationReflection
40
+ association
41
+ else
42
+ raise ArgumentError, "Unrecognized association #{association.inspect}; must be a Symbol, String, or AssociationReflection."
43
+ end
44
+ case r.macro
45
+ when :belongs_to
46
+ #if self.column_names.include?(r.primary_key_name.to_s) # primary_key_name is deprecated in rails 4
47
+ if self.column_names.include?(r.foreign_key.to_s)
48
+ if !r.options[:foreign_type] || self.column_names.include?(r.options[:foreign_type])
49
+ options = r.options.merge(
50
+ :class_name => r.class_name,
51
+ # :foreign_key => r.primary_key_name
52
+ :foreign_key => r.foreign_key
53
+ )
54
+ belongs_to r.name, options
55
+ end
56
+ end
57
+ when :has_many
58
+ ### TODO :through assocications
59
+ options = r.options.merge(
60
+ :class_name => r.class_name,
61
+ # :foreign_key => r.primary_key_name
62
+ :foreign_key => r.foreign_key
63
+ )
64
+ has_many r.name, options
65
+ when :has_and_belongs_to_many
66
+ options = r.options.merge(
67
+ :class_name => r.class_name,
68
+ # :foreign_key => r.primary_key_name,
69
+ :foreign_key => r.foreign_key,
70
+ :association_foreign_key => r.association_foreign_key
71
+ )
72
+ has_and_belongs_to_many r.name, options
73
+ when :has_one
74
+ ### TODO
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -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,63 @@
1
+ module RailsSqlViews4
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,85 @@
1
+ module RailsSqlViews4
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
+ # TODO : est appelé avec SQLITE, alors que c'est pas ok
62
+ def drop_table_with_cascade(table_name, options = {})
63
+ # execute "DROP TABLE #{quote_table_name(table_name)} CASCADE"
64
+ if supports_drop_table_cascade?
65
+ execute "DROP TABLE #{quote_table_name(table_name)} CASCADE"
66
+ else
67
+ execute "DROP TABLE #{quote_table_name(table_name)}"
68
+ end
69
+ end
70
+
71
+ # Drop a view.
72
+ # The +options+ hash can include the following keys:
73
+ # [<tt>:drop_behavior</tt>]
74
+ # Specify the drop behavior. ANSI SQL 92 defines two drop behaviors, CASCADE and RESTRICT. See your
75
+ # database documentation to determine what drop behaviors are available.
76
+ def drop_view(name, options={})
77
+ if supports_views?
78
+ drop_sql = "DROP VIEW #{quote_table_name(name)}"
79
+ drop_sql << " #{options[:drop_behavior]}" if options[:drop_behavior]
80
+ execute drop_sql
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,41 @@
1
+ module RailsSqlViews4
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,66 @@
1
+ module RailsSqlViews4
2
+ module ConnectionAdapters
3
+ module Mysql2Adapter
4
+ REQUIRED_METHODS = [:module RailsSqlViews4]
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,66 @@
1
+ module RailsSqlViews4
2
+ module ConnectionAdapters
3
+ module MysqlAdapter
4
+ REQUIRED_METHODS = [:module RailsSqlViews4]
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 RailsSqlViews4
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 RailsSqlViews4
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 RailsSqlViews4
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