aspgems-redhillonrails_core 2.0.0.beta2 → 2.0.0.beta4
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.
- data/.gitignore +8 -0
- data/.travis.yml +8 -0
- data/CHANGELOG +16 -0
- data/README.md +50 -10
- data/README_DEV.md +41 -0
- data/Rakefile +43 -13
- data/Thorfile +45 -0
- data/gemfiles/rails-3.0.7 +13 -0
- data/gemfiles/rails-3.0.7.lock +90 -0
- data/gemfiles/rails-3.0.8 +13 -0
- data/gemfiles/rails-3.0.8.lock +90 -0
- data/gemfiles/rails-3.0.9 +13 -0
- data/gemfiles/rails-3.0.9.lock +92 -0
- data/gemfiles/rails-3.1.0.rc5 +13 -0
- data/gemfiles/rails-3.1.0.rc5.lock +106 -0
- data/lib/redhillonrails_core.rb +12 -0
- data/lib/redhillonrails_core/active_record/base.rb +1 -1
- data/lib/redhillonrails_core/active_record/connection_adapters/abstract/foreign_key_definition.rb +13 -6
- data/lib/redhillonrails_core/active_record/connection_adapters/abstract/index_definition.rb +3 -0
- data/lib/redhillonrails_core/active_record/connection_adapters/abstract_adapter.rb +10 -6
- data/lib/redhillonrails_core/active_record/connection_adapters/mysql_adapter.rb +27 -53
- data/lib/redhillonrails_core/active_record/connection_adapters/postgresql_adapter.rb +82 -57
- data/lib/redhillonrails_core/active_record/migration/command_recorder.rb +30 -0
- data/lib/redhillonrails_core/active_record/schema_dumper.rb +18 -6
- data/lib/redhillonrails_core/version.rb +1 -1
- data/redhillonrails_core.gemspec +2 -1
- data/spec/command_recorder_spec.rb +39 -0
- data/spec/connections/mysql/connection.rb +4 -6
- data/spec/connections/mysql2/connection.rb +4 -6
- data/spec/connections/postgresql/connection.rb +4 -3
- data/spec/connections/sqlite3/connection.rb +4 -3
- data/spec/foreign_key_definition_spec.rb +31 -2
- data/spec/foreign_key_spec.rb +15 -2
- data/spec/migration_spec.rb +34 -0
- data/spec/table_definition_spec.rb +28 -0
- metadata +30 -11
@@ -3,7 +3,7 @@ module RedhillonrailsCore::ActiveRecord::ConnectionAdapters
|
|
3
3
|
def self.included(base)
|
4
4
|
base.class_eval do
|
5
5
|
alias_method_chain :remove_column, :redhillonrails_core
|
6
|
-
alias_method_chain :
|
6
|
+
alias_method_chain :structure_dump, :views
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
@@ -16,7 +16,7 @@ module RedhillonrailsCore::ActiveRecord::ConnectionAdapters
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def remove_foreign_key(table_name, foreign_key_name)
|
19
|
-
execute "ALTER TABLE #{table_name} DROP FOREIGN KEY #{foreign_key_name}"
|
19
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} DROP FOREIGN KEY #{foreign_key_name}"
|
20
20
|
end
|
21
21
|
|
22
22
|
def remove_column_with_redhillonrails_core(table_name, *column_names)
|
@@ -28,7 +28,6 @@ module RedhillonrailsCore::ActiveRecord::ConnectionAdapters
|
|
28
28
|
remove_column_without_redhillonrails_core(table_name, column_name)
|
29
29
|
end
|
30
30
|
end
|
31
|
-
alias :remove_columns_with_redhillonrails_core :remove_column_with_redhillonrails_core
|
32
31
|
|
33
32
|
def foreign_keys(table_name, name = nil)
|
34
33
|
results = execute("SHOW CREATE TABLE #{quote_table_name(table_name)}", name)
|
@@ -58,64 +57,19 @@ module RedhillonrailsCore::ActiveRecord::ConnectionAdapters
|
|
58
57
|
foreign_keys
|
59
58
|
end
|
60
59
|
|
61
|
-
# def reverse_foreign_keys(table_name, name = nil)
|
62
|
-
# results = execute(<<-SQL, name)
|
63
|
-
# SELECT constraint_name, table_name, column_name, referenced_table_name, referenced_column_name
|
64
|
-
# FROM information_schema.key_column_usage
|
65
|
-
# WHERE table_schema = SCHEMA()
|
66
|
-
# AND referenced_table_schema = table_schema
|
67
|
-
# ORDER BY constraint_name, ordinal_position;
|
68
|
-
# SQL
|
69
|
-
# current_foreign_key = nil
|
70
|
-
# foreign_keys = []
|
71
|
-
#
|
72
|
-
# results.each do |row|
|
73
|
-
# next unless table_name.casecmp(row[3]) == 0
|
74
|
-
# if current_foreign_key != row[0]
|
75
|
-
# foreign_keys << ForeignKeyDefinition.new(row[0], row[1], [], row[3], [])
|
76
|
-
# current_foreign_key = row[0]
|
77
|
-
# end
|
78
|
-
#
|
79
|
-
# foreign_keys.last.column_names << row[2]
|
80
|
-
# foreign_keys.last.references_column_names << row[4]
|
81
|
-
# end
|
82
|
-
#
|
83
|
-
# foreign_keys
|
84
|
-
# end
|
85
|
-
|
86
60
|
def reverse_foreign_keys(table_name, name = nil)
|
87
|
-
# @@schema ||= nil
|
88
|
-
# @@schema_version ||= 0
|
89
|
-
# current_version = ActiveRecord::Migrator.current_version
|
90
|
-
# if @@schema.nil? || @@schema_version != current_version
|
91
|
-
# @@schema_version = current_version
|
92
|
-
# ans = execute(<<-SQL, name)
|
93
|
-
# SELECT constraint_name, table_name, column_name, referenced_table_name, referenced_column_name
|
94
|
-
# FROM information_schema.key_column_usage
|
95
|
-
# WHERE table_schema = SCHEMA()
|
96
|
-
# AND referenced_table_schema = table_schema
|
97
|
-
# ORDER BY constraint_name, ordinal_position;
|
98
|
-
# SQL
|
99
|
-
# @@schema = []
|
100
|
-
# ans.each do | row |
|
101
|
-
# @@schema << [row[0], row[1], row[2], row[3], row[4]]
|
102
|
-
# end
|
103
|
-
# end
|
104
|
-
# results = @@schema
|
105
|
-
|
106
61
|
results = execute(<<-SQL, name)
|
107
62
|
SELECT constraint_name, table_name, column_name, referenced_table_name, referenced_column_name
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
63
|
+
FROM information_schema.key_column_usage
|
64
|
+
WHERE table_schema = SCHEMA()
|
65
|
+
AND referenced_table_schema = table_schema
|
66
|
+
ORDER BY constraint_name, ordinal_position;
|
112
67
|
SQL
|
113
|
-
|
114
68
|
current_foreign_key = nil
|
115
69
|
foreign_keys = []
|
116
70
|
|
117
71
|
results.each do |row|
|
118
|
-
next
|
72
|
+
next unless table_name.to_s.casecmp(row[3].to_s) == 0
|
119
73
|
if current_foreign_key != row[0]
|
120
74
|
foreign_keys << ForeignKeyDefinition.new(row[0], row[1], [], row[3], [])
|
121
75
|
current_foreign_key = row[0]
|
@@ -127,5 +81,25 @@ module RedhillonrailsCore::ActiveRecord::ConnectionAdapters
|
|
127
81
|
|
128
82
|
foreign_keys
|
129
83
|
end
|
84
|
+
|
85
|
+
def views(name = nil)
|
86
|
+
views = []
|
87
|
+
execute("SHOW FULL TABLES WHERE TABLE_TYPE='VIEW'", name).each { |row| views << row[0] }
|
88
|
+
views
|
89
|
+
end
|
90
|
+
|
91
|
+
def view_definition(view_name, name = nil)
|
92
|
+
select_one("SHOW CREATE VIEW #{quote_table_name(view_name)}", name)["Create View"]
|
93
|
+
end
|
94
|
+
|
95
|
+
def structure_dump_with_views
|
96
|
+
structure = structure_dump_without_views
|
97
|
+
|
98
|
+
views.each do |view|
|
99
|
+
structure += view_definition(view) + ";\n\n"
|
100
|
+
end
|
101
|
+
|
102
|
+
structure
|
103
|
+
end
|
130
104
|
end
|
131
105
|
end
|
@@ -2,61 +2,75 @@ module RedhillonrailsCore::ActiveRecord::ConnectionAdapters
|
|
2
2
|
module PostgresqlAdapter
|
3
3
|
def self.included(base)
|
4
4
|
base.class_eval do
|
5
|
-
|
5
|
+
remove_method :indexes
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
-
def set_table_comment(table_name, comment)
|
10
|
-
execute "COMMENT ON TABLE #{table_name} IS '#{quote_string(comment)}'"
|
11
|
-
end
|
12
|
-
|
13
|
-
def clear_table_comment(table_name)
|
14
|
-
execute "COMMENT ON TABLE #{table_name} IS NULL"
|
15
|
-
end
|
16
|
-
|
17
9
|
def add_index(table_name, column_name, options = {})
|
10
|
+
column_name, options = [], column_name if column_name.is_a?(Hash)
|
18
11
|
column_names = Array(column_name)
|
19
|
-
|
12
|
+
if column_names.empty?
|
13
|
+
raise ArgumentError, "No columns and :expression missing from options - cannot create index" if options[:expression].blank?
|
14
|
+
raise ArgumentError, "Index name not given. Pass :name option" if options[:name].blank?
|
15
|
+
end
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
index_type = options[:unique] ? "UNIQUE" : ""
|
18
|
+
index_name = options[:name] || index_name(table_name, column_names)
|
19
|
+
conditions = options[:conditions]
|
20
|
+
|
21
|
+
if column_names.empty? then
|
22
|
+
sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{options[:expression]}"
|
24
23
|
else
|
25
|
-
|
26
|
-
end
|
24
|
+
quoted_column_names = column_names.map { |e| options[:case_sensitive] == false && e.to_s !~ /_id$/ ? "LOWER(#{quote_column_name(e)})" : quote_column_name(e) }
|
27
25
|
|
28
|
-
|
26
|
+
sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names.join(", ")})"
|
27
|
+
sql += " WHERE (#{ ::ActiveRecord::Base.send(:sanitize_sql, conditions, quote_table_name(table_name)) })" if conditions
|
28
|
+
end
|
29
|
+
execute sql
|
30
|
+
end
|
29
31
|
|
30
|
-
|
32
|
+
def supports_partial_indexes?
|
33
|
+
true
|
31
34
|
end
|
32
35
|
|
33
|
-
def
|
34
|
-
|
36
|
+
def indexes(table_name, name = nil)
|
37
|
+
schemas = schema_search_path.split(/,/).map { |p| quote(p) }.join(',')
|
35
38
|
result = query(<<-SQL, name)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
SELECT distinct i.relname, d.indisunique, d.indkey, m.amname, t.oid,
|
40
|
+
pg_get_expr(d.indpred, t.oid), pg_get_expr(d.indexprs, t.oid)
|
41
|
+
FROM pg_class t, pg_class i, pg_index d, pg_am m
|
42
|
+
WHERE i.relkind = 'i'
|
43
|
+
AND i.relam = m.oid
|
44
|
+
AND d.indexrelid = i.oid
|
45
|
+
AND d.indisprimary = 'f'
|
46
|
+
AND t.oid = d.indrelid
|
47
|
+
AND t.relname = '#{table_name}'
|
48
|
+
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname IN (#{schemas}) )
|
49
|
+
ORDER BY i.relname
|
43
50
|
SQL
|
44
51
|
|
45
|
-
result.
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
result.map do |(index_name, is_unique, indkey, kind, oid, conditions, expression)|
|
53
|
+
unique = (is_unique == 't')
|
54
|
+
index_keys = indkey.split(" ")
|
55
|
+
|
56
|
+
columns = Hash[query(<<-SQL, "Columns for index #{index_name} on #{table_name}")]
|
57
|
+
SELECT a.attnum, a.attname
|
58
|
+
FROM pg_attribute a
|
59
|
+
WHERE a.attrelid = #{oid}
|
60
|
+
AND a.attnum IN (#{index_keys.join(",")})
|
61
|
+
SQL
|
62
|
+
|
63
|
+
column_names = columns.values_at(*index_keys).compact
|
64
|
+
if md = expression.try(:match, /^lower\(\(?([^)]+)\)?(::text)?\)$/i)
|
65
|
+
column_names << md[1]
|
56
66
|
end
|
67
|
+
index = ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names)
|
68
|
+
index.conditions = conditions
|
69
|
+
index.case_sensitive = !(expression =~ /lower/i)
|
70
|
+
index.kind = kind unless kind.downcase == "btree"
|
71
|
+
index.expression = expression
|
72
|
+
index
|
57
73
|
end
|
58
|
-
|
59
|
-
indexes
|
60
74
|
end
|
61
75
|
|
62
76
|
def foreign_keys(table_name, name = nil)
|
@@ -88,7 +102,7 @@ module RedhillonrailsCore::ActiveRecord::ConnectionAdapters
|
|
88
102
|
WHERE schemaname IN (#{schemas})
|
89
103
|
SQL
|
90
104
|
end
|
91
|
-
|
105
|
+
|
92
106
|
def view_definition(view_name, name = nil)
|
93
107
|
result = query(<<-SQL, name)
|
94
108
|
SELECT pg_get_viewdef(oid)
|
@@ -106,26 +120,37 @@ module RedhillonrailsCore::ActiveRecord::ConnectionAdapters
|
|
106
120
|
foreign_keys = []
|
107
121
|
|
108
122
|
query(sql, name).each do |row|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
123
|
+
if row[1] =~ /^FOREIGN KEY \((.+?)\) REFERENCES (.+?)\((.+?)\)( ON UPDATE (.+?))?( ON DELETE (.+?))?( (DEFERRABLE|NOT DEFERRABLE))?$/
|
124
|
+
name = row[0]
|
125
|
+
from_table_name = row[2]
|
126
|
+
column_names = $1
|
127
|
+
references_table_name = $2
|
128
|
+
references_column_names = $3
|
129
|
+
on_update = $5
|
130
|
+
on_delete = $7
|
131
|
+
deferrable = $9 == "DEFERRABLE"
|
132
|
+
on_update = on_update.downcase.gsub(' ', '_').to_sym if on_update
|
133
|
+
on_delete = on_delete.downcase.gsub(' ', '_').to_sym if on_delete
|
134
|
+
|
135
|
+
foreign_keys << ForeignKeyDefinition.new(name,
|
136
|
+
from_table_name, column_names.split(', '),
|
137
|
+
references_table_name.sub(/^"(.*)"$/, '\1'), references_column_names.split(', '),
|
138
|
+
on_update, on_delete, deferrable)
|
139
|
+
end
|
126
140
|
end
|
127
141
|
|
128
142
|
foreign_keys
|
129
143
|
end
|
144
|
+
|
145
|
+
# Converts form like: column1, LOWER(column2)
|
146
|
+
# to: column1, column2
|
147
|
+
def determine_index_column_names(column_definitions)
|
148
|
+
column_definitions.split(", ").map do |name|
|
149
|
+
name = $1 if name =~ /^LOWER\(([^:]+)(::text)?\)$/i
|
150
|
+
name = $1 if name =~ /^"(.*)"$/
|
151
|
+
name
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
130
155
|
end
|
131
156
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RedhillonrailsCore
|
2
|
+
module ActiveRecord
|
3
|
+
module Migration
|
4
|
+
module CommandRecorder
|
5
|
+
def add_foreign_key(*args)
|
6
|
+
record(:add_foreign_key, args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def remove_foreign_key(*args)
|
10
|
+
record(:remove_foreign_key, args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def invert_add_foreign_key(args)
|
14
|
+
from_table, to_table, add_options = *args
|
15
|
+
add_options ||= {}
|
16
|
+
|
17
|
+
if add_options[:name]
|
18
|
+
options = {:name => add_options[:name]}
|
19
|
+
elsif add_options[:column]
|
20
|
+
options = {:column => add_options[:column]}
|
21
|
+
else
|
22
|
+
options = to_table
|
23
|
+
end
|
24
|
+
|
25
|
+
[:remove_foreign_key, [from_table, options]]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -25,12 +25,24 @@ module RedhillonrailsCore::ActiveRecord
|
|
25
25
|
def indexes_with_redhillonrails_core(table, stream)
|
26
26
|
if (indexes = @connection.indexes(table)).any?
|
27
27
|
add_index_statements = indexes.map do |index|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
|
29
|
+
if index.columns.any?
|
30
|
+
statement_parts = [('add_index ' + index.table.inspect)]
|
31
|
+
statement_parts << index.columns.inspect
|
32
|
+
statement_parts << (':name => ' + index.name.inspect)
|
33
|
+
statement_parts << ':unique => true' if index.unique
|
34
|
+
# This only used in postgresql - :case_sensitive, :conditions, :kind, :expression
|
35
|
+
statement_parts << ':case_sensitive => false' unless index.case_sensitive?
|
36
|
+
statement_parts << ':conditions => ' + index.conditions.inspect unless index.conditions.blank?
|
37
|
+
statement_parts << ':kind => ' + index.kind.inspect unless index.kind.blank?
|
38
|
+
statement_parts << ':expression => ' + index.expression.inspect unless index.expression.blank?
|
39
|
+
else
|
40
|
+
# This only used in postgresql - :case_sensitive, :conditions, :kind, :expression
|
41
|
+
statement_parts = [('add_index ' + index.table.inspect)]
|
42
|
+
statement_parts << (':name => ' + index.name.inspect)
|
43
|
+
statement_parts << ':kind => ' + index.kind.inspect unless index.kind.blank?
|
44
|
+
statement_parts << ':expression => ' + index.expression.inspect unless index.expression.blank?
|
45
|
+
end
|
34
46
|
|
35
47
|
if index.respond_to?(:lengths)
|
36
48
|
index_lengths = index.lengths.compact if index.lengths.is_a?(Array)
|
data/redhillonrails_core.gemspec
CHANGED
@@ -20,7 +20,8 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.add_dependency("activerecord", ">= 2")
|
21
21
|
s.add_dependency("activesupport", ">= 2")
|
22
22
|
|
23
|
-
|
23
|
+
# Development dependencies through thorfile
|
24
|
+
s.add_development_dependency("rspec", "~> 2.6.0")
|
24
25
|
s.add_development_dependency("pg")
|
25
26
|
s.add_development_dependency("mysql")
|
26
27
|
s.add_development_dependency("mysql2")
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'Command Recorder' do
|
4
|
+
if defined?(ActiveRecord::Migration::CommandRecorder)
|
5
|
+
before do
|
6
|
+
@recorder = ActiveRecord::Migration::CommandRecorder.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'invert_add_foreign_key' do
|
10
|
+
@recorder.add_foreign_key(:employees, :companies)
|
11
|
+
remove = @recorder.inverse.first
|
12
|
+
remove.should == [:remove_foreign_key, [:employees, :companies]]
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'invert_add_foreign_key with column' do
|
16
|
+
@recorder.add_foreign_key(:employees, :companies, :column => :place_id)
|
17
|
+
remove = @recorder.inverse.first
|
18
|
+
remove.should == [:remove_foreign_key, [:employees, {:column => :place_id}]]
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'invert_add_foreign_key with name' do
|
22
|
+
@recorder.add_foreign_key(:employees, :companies, :name => 'the_best_fk', :column => :place_id)
|
23
|
+
remove = @recorder.inverse.first
|
24
|
+
remove.should == [:remove_foreign_key, [:employees, {:name => 'the_best_fk'}]]
|
25
|
+
|
26
|
+
@recorder.record :rename_table, [:old, :new]
|
27
|
+
rename = @recorder.inverse.first
|
28
|
+
rename.should == [:rename_table, [:new, :old]]
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'remove_foreign_key is irreversible' do
|
32
|
+
@recorder.remove_foreign_key(:employees, :companies)
|
33
|
+
expect {
|
34
|
+
@recorder.inverse
|
35
|
+
}.to raise_error(ActiveRecord::IrreversibleMigration)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -4,15 +4,13 @@ require 'logger'
|
|
4
4
|
ActiveRecord::Base.logger = Logger.new("debug.log")
|
5
5
|
|
6
6
|
ActiveRecord::Base.configurations = {
|
7
|
-
'
|
7
|
+
'mysql' => {
|
8
8
|
:adapter => 'mysql',
|
9
|
-
:database => '
|
10
|
-
:username => '
|
9
|
+
:database => 'redhillonrails_core',
|
10
|
+
:username => (ENV["TRAVIS"] ? '' : 'redhillonrails'),
|
11
11
|
:encoding => 'utf8',
|
12
|
-
:socket => '/var/run/mysqld/mysqld.sock',
|
13
|
-
:min_messages => 'warning'
|
14
12
|
}
|
15
13
|
|
16
14
|
}
|
17
15
|
|
18
|
-
ActiveRecord::Base.establish_connection '
|
16
|
+
ActiveRecord::Base.establish_connection 'mysql'
|
@@ -4,15 +4,13 @@ require 'logger'
|
|
4
4
|
ActiveRecord::Base.logger = Logger.new("debug.log")
|
5
5
|
|
6
6
|
ActiveRecord::Base.configurations = {
|
7
|
-
'
|
7
|
+
'mysql2' => {
|
8
8
|
:adapter => 'mysql2',
|
9
|
-
:database => '
|
10
|
-
:username => '
|
9
|
+
:database => 'redhillonrails_core',
|
10
|
+
:username => (ENV["TRAVIS"] ? '' : 'redhillonrails'),
|
11
11
|
:encoding => 'utf8',
|
12
|
-
:socket => '/var/run/mysqld/mysqld.sock',
|
13
|
-
:min_messages => 'warning'
|
14
12
|
}
|
15
13
|
|
16
14
|
}
|
17
15
|
|
18
|
-
ActiveRecord::Base.establish_connection '
|
16
|
+
ActiveRecord::Base.establish_connection 'mysql2'
|