schema_plus 1.8.9 → 2.0.0.pre1
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 +4 -4
- data/.gitignore +4 -4
- data/.travis.yml +1 -47
- data/CHANGELOG.md +0 -35
- data/README.md +73 -107
- data/Rakefile +7 -10
- data/TODO.md +51 -0
- data/gemfiles/Gemfile.base +2 -0
- data/lib/schema_column_plus.rb +7 -0
- data/lib/{schema_plus → schema_column_plus}/active_record/connection_adapters/column.rb +13 -11
- data/lib/schema_column_plus/middleware/model.rb +22 -0
- data/lib/schema_db_default.rb +13 -0
- data/lib/{schema_plus → schema_db_default}/active_record/attribute.rb +4 -4
- data/lib/schema_db_default/db_default.rb +17 -0
- data/lib/schema_db_default/middleware.rb +30 -0
- data/lib/schema_default_expr.rb +32 -0
- data/lib/schema_default_expr/active_record/connection_adapters/mysql_adapter.rb +17 -0
- data/lib/schema_default_expr/active_record/connection_adapters/postgresql_adapter.rb +18 -0
- data/lib/schema_default_expr/active_record/connection_adapters/sqlite3_adapter.rb +35 -0
- data/lib/schema_default_expr/middleware.rb +54 -0
- data/lib/schema_pg_enums.rb +6 -0
- data/lib/schema_pg_enums/active_record.rb +69 -0
- data/lib/schema_pg_enums/middleware.rb +23 -0
- data/lib/schema_plus.rb +17 -45
- data/lib/schema_plus/active_record/base.rb +6 -23
- data/lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb +80 -181
- data/lib/schema_plus/active_record/connection_adapters/foreign_key_definition.rb +78 -99
- data/lib/schema_plus/active_record/connection_adapters/mysql_adapter.rb +34 -114
- data/lib/schema_plus/active_record/connection_adapters/postgresql_adapter.rb +16 -370
- data/lib/schema_plus/active_record/connection_adapters/schema_statements.rb +1 -67
- data/lib/schema_plus/active_record/connection_adapters/sqlite3_adapter.rb +18 -112
- data/lib/schema_plus/active_record/connection_adapters/table_definition.rb +14 -116
- data/lib/schema_plus/active_record/migration/command_recorder.rb +8 -59
- data/lib/schema_plus/middleware/dumper.rb +94 -0
- data/lib/schema_plus/middleware/migration.rb +167 -0
- data/lib/schema_plus/middleware/model.rb +17 -0
- data/lib/schema_plus/version.rb +1 -1
- data/lib/schema_plus_tables.rb +15 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/abstract_adapter.rb +20 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/mysql_adapter.rb +25 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/postgresql_adapter.rb +13 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/sqlite3_adapter.rb +12 -0
- data/lib/schema_views.rb +16 -0
- data/lib/schema_views/active_record/connection_adapters/abstract_adapter.rb +41 -0
- data/lib/schema_views/active_record/connection_adapters/mysql_adapter.rb +30 -0
- data/lib/schema_views/active_record/connection_adapters/postgresql_adapter.rb +31 -0
- data/lib/schema_views/active_record/connection_adapters/sqlite3_adapter.rb +18 -0
- data/lib/schema_views/middleware.rb +47 -0
- data/schema_dev.yml +1 -31
- data/schema_plus.gemspec +11 -9
- data/spec/foreign_key_definition_spec.rb +7 -7
- data/spec/foreign_key_spec.rb +63 -48
- data/spec/migration_spec.rb +58 -203
- data/spec/named_schemas_spec.rb +5 -88
- data/spec/{column_spec.rb → schema_column_plus/column_spec.rb} +26 -48
- data/spec/schema_db_default/column_spec.rb +58 -0
- data/spec/{column_default_spec.rb → schema_default_expr/column_default_spec.rb} +1 -2
- data/spec/schema_default_expr/schema_dumper_spec.rb +116 -0
- data/spec/schema_dumper_spec.rb +22 -327
- data/spec/{enum_spec.rb → schema_pg_enums/enum_spec.rb} +1 -1
- data/spec/schema_pg_enums/schema_dumper_spec.rb +37 -0
- data/spec/schema_views/named_schemas_spec.rb +97 -0
- data/spec/{views_spec.rb → schema_views/views_spec.rb} +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/support/matchers/reference.rb +11 -12
- metadata +104 -57
- data/gemfiles/rails-3.2/Gemfile.base +0 -3
- data/gemfiles/rails-3.2/Gemfile.mysql +0 -10
- data/gemfiles/rails-3.2/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-3.2/Gemfile.postgresql +0 -10
- data/gemfiles/rails-3.2/Gemfile.sqlite3 +0 -10
- data/gemfiles/rails-4.0/Gemfile.base +0 -3
- data/gemfiles/rails-4.0/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-4.0/Gemfile.postgresql +0 -10
- data/gemfiles/rails-4.0/Gemfile.sqlite3 +0 -10
- data/gemfiles/rails-4.1/Gemfile.base +0 -3
- data/gemfiles/rails-4.1/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-4.1/Gemfile.postgresql +0 -10
- data/gemfiles/rails-4.1/Gemfile.sqlite3 +0 -10
- data/lib/schema_plus/active_record/column_options_handler.rb +0 -117
- data/lib/schema_plus/active_record/connection_adapters/index_definition.rb +0 -70
- data/lib/schema_plus/active_record/db_default.rb +0 -19
- data/lib/schema_plus/active_record/foreign_keys.rb +0 -137
- data/lib/schema_plus/active_record/schema_dumper.rb +0 -171
- data/lib/schema_plus/railtie.rb +0 -20
- data/spec/index_definition_spec.rb +0 -211
- data/spec/index_spec.rb +0 -249
@@ -0,0 +1,94 @@
|
|
1
|
+
module SchemaPlus
|
2
|
+
module Middleware
|
3
|
+
module Dumper
|
4
|
+
|
5
|
+
def self.insert
|
6
|
+
SchemaMonkey::Middleware::Dumper::Tables.prepend FkDependencies
|
7
|
+
SchemaMonkey::Middleware::Dumper::Tables.append IgnoreActiveRecordFkDumps
|
8
|
+
SchemaMonkey::Middleware::Dumper::Table.append ForeignKeys
|
9
|
+
end
|
10
|
+
|
11
|
+
# index and foreign key constraint definitions are dumped
|
12
|
+
# inline in the create_table block. (This is done for elegance, but
|
13
|
+
# also because Sqlite3 does not allow foreign key constraints to be
|
14
|
+
# added to a table after it has been defined.)
|
15
|
+
|
16
|
+
#
|
17
|
+
# Middleware for the collection of tables
|
18
|
+
#
|
19
|
+
|
20
|
+
class FkDependencies < SchemaMonkey::Middleware::Base
|
21
|
+
|
22
|
+
def call(env)
|
23
|
+
@inline_fks = Hash.new{ |h, k| h[k] = [] }
|
24
|
+
@backref_fks = Hash.new{ |h, k| h[k] = [] }
|
25
|
+
|
26
|
+
env.connection.tables.each do |table|
|
27
|
+
@inline_fks[table] = env.connection.foreign_keys(table)
|
28
|
+
env.dump.depends(table, @inline_fks[table].collect(&:to_table))
|
29
|
+
end
|
30
|
+
|
31
|
+
# Normally we dump foreign key constraints inline in the table
|
32
|
+
# definitions, both for visual cleanliness and because sqlite3
|
33
|
+
# doesn't allow foreign key constraints to be added afterwards.
|
34
|
+
# But in case there's a cycle in the constraint references, some
|
35
|
+
# constraints will need to be broken out then added later. (Adding
|
36
|
+
# constraints later won't work with sqlite3, but that means sqlite3
|
37
|
+
# won't let you create cycles in the first place.)
|
38
|
+
break_fk_cycles(env) while env.dump.strongly_connected_components.any?{|component| component.size > 1}
|
39
|
+
|
40
|
+
env.dump.data.inline_fks = @inline_fks
|
41
|
+
env.dump.data.backref_fks = @backref_fks
|
42
|
+
|
43
|
+
continue env
|
44
|
+
end
|
45
|
+
|
46
|
+
def break_fk_cycles(env) #:nodoc:
|
47
|
+
env.dump.strongly_connected_components.select{|component| component.size > 1}.each do |tables|
|
48
|
+
table = tables.sort.first
|
49
|
+
backref_fks = @inline_fks[table].select{|fk| tables.include?(fk.to_table)}
|
50
|
+
@inline_fks[table] -= backref_fks
|
51
|
+
env.dump.dependencies[table] -= backref_fks.collect(&:to_table)
|
52
|
+
backref_fks.each do |fk|
|
53
|
+
@backref_fks[fk.to_table] << fk
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class IgnoreActiveRecordFkDumps < SchemaMonkey::Middleware::Base
|
60
|
+
# Ignore the foreign key dumps at the end of the schema; we'll put them in/near their tables
|
61
|
+
def call(env)
|
62
|
+
continue env
|
63
|
+
env.dump.foreign_keys = []
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Middleware for individual tables
|
69
|
+
#
|
70
|
+
class ForeignKeys < SchemaMonkey::Middleware::Base
|
71
|
+
def call(env)
|
72
|
+
continue env
|
73
|
+
dumped = {}
|
74
|
+
env.table.columns.each do |column|
|
75
|
+
if (foreign_key = env.dump.data.inline_fks[env.table.name].find(&its.column.to_s == column.name))
|
76
|
+
column.add_option foreign_key.to_dump(column: true)
|
77
|
+
dumped[foreign_key] = true
|
78
|
+
end
|
79
|
+
if (foreign_key = env.dump.data.backref_fks.values.flatten.find{|fk| fk.from_table.to_s == env.table.name && fk.column.to_s == column.name})
|
80
|
+
column.add_comment "foreign key references #{foreign_key.to_table.inspect} (below)"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
env.table.statements += env.dump.data.inline_fks[env.table.name].map { |foreign_key|
|
84
|
+
foreign_key.to_dump(inline: true) unless dumped[foreign_key]
|
85
|
+
}.compact.sort
|
86
|
+
env.table.trailer += env.dump.data.backref_fks[env.table.name].map { |foreign_key|
|
87
|
+
foreign_key.to_dump
|
88
|
+
}.sort
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
module SchemaPlus
|
2
|
+
module Middleware
|
3
|
+
module Migration
|
4
|
+
|
5
|
+
def self.insert
|
6
|
+
SchemaMonkey::Middleware::Migration::Column.prepend Shortcuts
|
7
|
+
SchemaMonkey::Middleware::Migration::Column.append AddForeignKeys
|
8
|
+
end
|
9
|
+
|
10
|
+
class Shortcuts < SchemaMonkey::Middleware::Base
|
11
|
+
def call(env)
|
12
|
+
fk_options = env.options[:foreign_key]
|
13
|
+
|
14
|
+
case fk_options
|
15
|
+
when false then ;
|
16
|
+
when true then fk_options = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
if fk_options != false # may be nil
|
20
|
+
[:references, :on_update, :on_delete, :deferrable].each do |key|
|
21
|
+
(fk_options||={}).reverse_merge!(key => env.options[key]) if env.options.has_key? key
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
if fk_options and fk_options.has_key?(:references)
|
26
|
+
case fk_options[:references]
|
27
|
+
when nil, false
|
28
|
+
fk_options = false
|
29
|
+
when Array then
|
30
|
+
table, primary_key = fk_options[:references]
|
31
|
+
fk_options[:references] = table
|
32
|
+
fk_options[:primary_key] ||= primary_key
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
fk_options = false if fk_options and fk_options.has_key?(:references) and not fk_options[:references]
|
38
|
+
|
39
|
+
env.options[:foreign_key] = fk_options
|
40
|
+
|
41
|
+
continue env
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class AddForeignKeys < SchemaMonkey::Middleware::Base
|
47
|
+
def call(env)
|
48
|
+
options = env.options
|
49
|
+
original_options = options.dup
|
50
|
+
|
51
|
+
is_reference = (env.type == :reference)
|
52
|
+
is_polymorphic = is_reference && options[:polymorphic]
|
53
|
+
|
54
|
+
# usurp index creation from AR. That's necessary to make
|
55
|
+
# auto_index work properly
|
56
|
+
index = options.delete(:index) unless is_polymorphic
|
57
|
+
options[:foreign_key] = false if is_reference
|
58
|
+
|
59
|
+
continue env
|
60
|
+
|
61
|
+
return if is_polymorphic
|
62
|
+
|
63
|
+
env.options = original_options
|
64
|
+
|
65
|
+
add_foreign_keys_and_auto_index(env)
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_foreign_keys_and_auto_index(env)
|
70
|
+
|
71
|
+
if (reverting = env.caller.is_a?(::ActiveRecord::Migration::CommandRecorder) && env.caller.reverting)
|
72
|
+
commands_length = env.caller.commands.length
|
73
|
+
end
|
74
|
+
|
75
|
+
config = (env.caller.try(:schema_plus_config) || SchemaPlus.config).foreign_keys
|
76
|
+
fk_args = get_fk_args(env, config)
|
77
|
+
|
78
|
+
# remove existing fk and auto-generated index in case of change of fk on existing column
|
79
|
+
if env.operation == :change and fk_args # includes :none for explicitly off
|
80
|
+
remove_foreign_key_if_exists(env)
|
81
|
+
remove_auto_index_if_exists(env)
|
82
|
+
end
|
83
|
+
|
84
|
+
fk_args = nil if fk_args == :none
|
85
|
+
|
86
|
+
create_index(env, fk_args, config)
|
87
|
+
create_fk(env, fk_args) if fk_args
|
88
|
+
|
89
|
+
if reverting
|
90
|
+
rev = []
|
91
|
+
while env.caller.commands.length > commands_length
|
92
|
+
cmd = env.caller.commands.pop
|
93
|
+
rev.unshift cmd unless cmd[0].to_s =~ /^add_/
|
94
|
+
end
|
95
|
+
env.caller.commands.concat rev
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
def auto_index_name(env)
|
101
|
+
ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.auto_index_name(env.table_name, env.column_name)
|
102
|
+
end
|
103
|
+
|
104
|
+
def create_index(env, fk_args, config)
|
105
|
+
# create index if requested explicity or implicitly due to auto_index
|
106
|
+
index = env.options[:index]
|
107
|
+
index = { :name => auto_index_name(env) } if index.nil? and fk_args && config.auto_index?
|
108
|
+
return unless index
|
109
|
+
case env.caller
|
110
|
+
when ::ActiveRecord::ConnectionAdapters::TableDefinition
|
111
|
+
env.caller.index(env.column_name, index)
|
112
|
+
else
|
113
|
+
env.caller.add_index(env.table_name, env.column_name, index)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_fk(env, fk_args)
|
118
|
+
references = fk_args.delete(:references)
|
119
|
+
case env.caller
|
120
|
+
when ::ActiveRecord::ConnectionAdapters::TableDefinition
|
121
|
+
env.caller.foreign_key(env.column_name, references, fk_args)
|
122
|
+
else
|
123
|
+
env.caller.add_foreign_key(env.table_name, references, fk_args.merge(:column => env.column_name))
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
def get_fk_args(env, config)
|
129
|
+
args = nil
|
130
|
+
column_name = env.column_name.to_s
|
131
|
+
options = env.options
|
132
|
+
|
133
|
+
return :none if options[:foreign_key] == false
|
134
|
+
|
135
|
+
args = options[:foreign_key]
|
136
|
+
args ||= {} if config.auto_create? and column_name =~ /_id$/
|
137
|
+
|
138
|
+
return nil if args.nil?
|
139
|
+
|
140
|
+
args[:references] ||= env.table_name if column_name == 'parent_id'
|
141
|
+
|
142
|
+
args[:references] ||= begin
|
143
|
+
table_name = column_name.sub(/_id$/, '')
|
144
|
+
table_name = table_name.pluralize if ::ActiveRecord::Base.pluralize_table_names
|
145
|
+
table_name
|
146
|
+
end
|
147
|
+
|
148
|
+
args[:on_update] ||= config.on_update
|
149
|
+
args[:on_delete] ||= config.on_delete
|
150
|
+
|
151
|
+
args
|
152
|
+
end
|
153
|
+
|
154
|
+
def remove_foreign_key_if_exists(env)
|
155
|
+
env.caller.remove_foreign_key(env.table_name.to_s, column: env.column_name.to_s, :if_exists => true)
|
156
|
+
end
|
157
|
+
|
158
|
+
def remove_auto_index_if_exists(env)
|
159
|
+
env.caller.remove_index(env.table_name, :name => auto_index_name(env), :column => env.column_name, :if_exists => true)
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SchemaPlus
|
2
|
+
module Middleware
|
3
|
+
module Model
|
4
|
+
|
5
|
+
def self.insert
|
6
|
+
SchemaMonkey::Middleware::Model::ResetColumnInformation.append ResetColumnInformation
|
7
|
+
end
|
8
|
+
|
9
|
+
class ResetColumnInformation < SchemaMonkey::Middleware::Base
|
10
|
+
def call(env)
|
11
|
+
continue env
|
12
|
+
env.model.reset_foreign_key_information
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/schema_plus/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'schema_monkey'
|
2
|
+
|
3
|
+
require_relative 'schema_plus_tables/active_record/connection_adapters/abstract_adapter'
|
4
|
+
|
5
|
+
module SchemaPlusTables
|
6
|
+
module ActiveRecord
|
7
|
+
module ConnectionAdapters
|
8
|
+
autoload :MysqlAdapter, 'schema_plus_tables/active_record/connection_adapters/mysql_adapter'
|
9
|
+
autoload :PostgresqlAdapter, 'schema_plus_tables/active_record/connection_adapters/postgresql_adapter'
|
10
|
+
autoload :Sqlite3Adapter, 'schema_plus_tables/active_record/connection_adapters/sqlite3_adapter'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
SchemaMonkey.register(SchemaPlusTables)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SchemaPlusTables
|
2
|
+
module ActiveRecord
|
3
|
+
module ConnectionAdapters
|
4
|
+
module AbstractAdapter
|
5
|
+
|
6
|
+
# Extends rails' drop_table to include these options:
|
7
|
+
# :cascade
|
8
|
+
# :if_exists
|
9
|
+
#
|
10
|
+
def drop_table(name, options = {})
|
11
|
+
sql = "DROP TABLE"
|
12
|
+
sql += " IF EXISTS" if options[:if_exists]
|
13
|
+
sql += " #{quote_table_name(name)}"
|
14
|
+
sql += " CASCADE" if options[:cascade]
|
15
|
+
execute sql
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SchemaPlusTables
|
2
|
+
module ActiveRecord
|
3
|
+
module ConnectionAdapters
|
4
|
+
module MysqlAdapter
|
5
|
+
|
6
|
+
# implement cascade by removing foreign keys
|
7
|
+
def drop_table(name, options={})
|
8
|
+
if options[:cascade]
|
9
|
+
reverse_foreign_keys(name).each do |foreign_key|
|
10
|
+
remove_foreign_key(foreign_key.from_table, name: foreign_key.name)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
sql = 'DROP'
|
15
|
+
sql += ' TEMPORARY' if options[:temporary]
|
16
|
+
sql += ' TABLE'
|
17
|
+
sql += ' IF EXISTS' if options[:if_exists]
|
18
|
+
sql += " #{quote_table_name(name)}"
|
19
|
+
|
20
|
+
execute sql
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SchemaPlusTables
|
2
|
+
module ActiveRecord
|
3
|
+
module ConnectionAdapters
|
4
|
+
module PostgresqlAdapter
|
5
|
+
# pg gem defines a drop_table with fewer options than our Abstract
|
6
|
+
# one, so use the abstract one instead
|
7
|
+
def drop_table(name, options={})
|
8
|
+
SchemaPlusTables::ActiveRecord::ConnectionAdapters::AbstractAdapter.instance_method(:drop_table).bind(self).call(name, options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/schema_views.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'schema_monkey'
|
2
|
+
|
3
|
+
require_relative 'schema_views/active_record/connection_adapters/abstract_adapter'
|
4
|
+
require_relative 'schema_views/middleware'
|
5
|
+
|
6
|
+
module SchemaViews
|
7
|
+
module ActiveRecord
|
8
|
+
module ConnectionAdapters
|
9
|
+
autoload :MysqlAdapter, 'schema_views/active_record/connection_adapters/mysql_adapter'
|
10
|
+
autoload :PostgresqlAdapter, 'schema_views/active_record/connection_adapters/postgresql_adapter'
|
11
|
+
autoload :Sqlite3Adapter, 'schema_views/active_record/connection_adapters/sqlite3_adapter'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
SchemaMonkey.register(SchemaViews)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SchemaViews
|
2
|
+
module ActiveRecord
|
3
|
+
module ConnectionAdapters
|
4
|
+
module AbstractAdapter
|
5
|
+
# Create a view given the SQL definition. Specify :force => true
|
6
|
+
# to first drop the view if it already exists.
|
7
|
+
def create_view(view_name, definition, options={})
|
8
|
+
definition = definition.to_sql if definition.respond_to? :to_sql
|
9
|
+
if options[:force]
|
10
|
+
drop_view(view_name, if_exists: true)
|
11
|
+
end
|
12
|
+
execute "CREATE VIEW #{quote_table_name(view_name)} AS #{definition}"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Drop the named view. Specify :if_exists => true
|
16
|
+
# to fail silently if the view doesn't exist.
|
17
|
+
def drop_view(view_name, options = {})
|
18
|
+
sql = "DROP VIEW"
|
19
|
+
sql += " IF EXISTS" if options[:if_exists]
|
20
|
+
sql += " #{quote_table_name(view_name)}"
|
21
|
+
execute sql
|
22
|
+
end
|
23
|
+
|
24
|
+
#####################################################################
|
25
|
+
#
|
26
|
+
# The functions below here are abstract; each subclass should
|
27
|
+
# define them all. Defining them here only for reference.
|
28
|
+
#
|
29
|
+
|
30
|
+
# (abstract) Returns the names of all views, as an array of strings
|
31
|
+
def views(name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; [] end
|
32
|
+
|
33
|
+
# (abstract) Returns the SQL definition of a given view. This is
|
34
|
+
# the literal SQL would come after 'CREATVE VIEW viewname AS ' in
|
35
|
+
# the SQL statement to create a view.
|
36
|
+
def view_definition(view_name, name = nil) raise "Internal Error: Connection adapter didn't override abstract function"; end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SchemaViews
|
2
|
+
module ActiveRecord
|
3
|
+
module ConnectionAdapters
|
4
|
+
module MysqlAdapter
|
5
|
+
|
6
|
+
def views(name = nil)
|
7
|
+
views = []
|
8
|
+
select_all("SELECT table_name FROM information_schema.views WHERE table_schema = SCHEMA()", name).each do |row|
|
9
|
+
views << row["table_name"]
|
10
|
+
end
|
11
|
+
views
|
12
|
+
end
|
13
|
+
|
14
|
+
def view_definition(view_name, name = nil)
|
15
|
+
results = select_all("SELECT view_definition, check_option FROM information_schema.views WHERE table_schema = SCHEMA() AND table_name = #{quote(view_name)}", name)
|
16
|
+
return nil unless results.any?
|
17
|
+
row = results.first
|
18
|
+
sql = row["view_definition"]
|
19
|
+
sql.gsub!(%r{#{quote_table_name(current_database)}[.]}, '')
|
20
|
+
case row["check_option"]
|
21
|
+
when "CASCADED" then sql += " WITH CASCADED CHECK OPTION"
|
22
|
+
when "LOCAL" then sql += " WITH LOCAL CHECK OPTION"
|
23
|
+
end
|
24
|
+
sql
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|