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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +121 -0
- data/lib/active_record/view.rb +80 -0
- data/lib/core_ext/module.rb +13 -0
- data/lib/rails_sql_views4/connection_adapters/abstract/schema_definitions.rb +63 -0
- data/lib/rails_sql_views4/connection_adapters/abstract/schema_statements.rb +85 -0
- data/lib/rails_sql_views4/connection_adapters/abstract_adapter.rb +41 -0
- data/lib/rails_sql_views4/connection_adapters/mysql2_adapter.rb +66 -0
- data/lib/rails_sql_views4/connection_adapters/mysql_adapter.rb +66 -0
- data/lib/rails_sql_views4/connection_adapters/oci_adapter.rb +33 -0
- data/lib/rails_sql_views4/connection_adapters/oracle_adapter.rb +33 -0
- data/lib/rails_sql_views4/connection_adapters/oracleenhanced_adapter.rb +39 -0
- data/lib/rails_sql_views4/connection_adapters/oracleenhanced_adapter.rb.orig +72 -0
- data/lib/rails_sql_views4/connection_adapters/postgresql_adapter.rb +69 -0
- data/lib/rails_sql_views4/connection_adapters/postgresql_adapter.rb.orig +69 -0
- data/lib/rails_sql_views4/connection_adapters/sqlite3_adapter.rb +68 -0
- data/lib/rails_sql_views4/connection_adapters/sqlite_adapter.rb +68 -0
- data/lib/rails_sql_views4/connection_adapters/sqlserver_adapter.rb +43 -0
- data/lib/rails_sql_views4/loader.rb +18 -0
- data/lib/rails_sql_views4/schema_dumper.rb +114 -0
- data/lib/rails_sql_views4/version.rb +3 -0
- data/lib/rails_sql_views4.rb +28 -0
- data/lib/tasks/rails_sql_views4_tasks.rake +4 -0
- data/test/README.NOT_UP_TO_DATE +63 -0
- data/test/adapter_test.rb +93 -0
- data/test/connection/native_mysql/connection.rb +32 -0
- data/test/connection/native_mysql/schema.sql +34 -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/connection.example.yml +12 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/item.rb +4 -0
- data/test/dummy/app/models/person.rb +5 -0
- data/test/dummy/app/models/person2.rb +4 -0
- data/test/dummy/app/models/place.rb +2 -0
- data/test/dummy/app/models/v_person.rb +8 -0
- data/test/dummy/app/models/v_profile.rb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +78 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/assets.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20141228200436_create_people.rb +10 -0
- data/test/dummy/db/migrate/20141228200437_create_people2.rb +11 -0
- data/test/dummy/db/migrate/20141228200438_create_places.rb +12 -0
- data/test/dummy/db/migrate/20141228200439_create_items.rb +8 -0
- data/test/dummy/db/migrate/20141228200440_create_items_people.rb +9 -0
- data/test/dummy/db/schema.rb +53 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +439 -0
- data/test/dummy/log/test.log +29320 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/test/fixtures/persons.yml +7 -0
- data/test/dummy/test/models/person_test.rb +7 -0
- data/test/rails_sql_views4_test.rb +11 -0
- data/test/schema.native_mysql.expected.rb +51 -0
- data/test/schema.native_postgresql.expected.rb +51 -0
- data/test/schema.native_postgresql.out.rb +69 -0
- data/test/schema.oracle_enhanced.expected.rb +51 -0
- data/test/schema_dumper_test.rb +134 -0
- data/test/test_helper.rb +41 -0
- data/test/test_helper.rb.old +30 -0
- data/test/view_model_test.rb +68 -0
- data/test/view_operations_test.rb +50 -0
- 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
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
|