rails_sql_views4 0.0.1

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 (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