active_shard 0.2.2 → 0.2.3
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/lib/active_shard/rails/database.rake +329 -0
- data/lib/active_shard/version.rb +1 -1
- metadata +2 -1
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
namespace :shards do
|
|
2
|
+
|
|
3
|
+
desc 'Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)'
|
|
4
|
+
task :create => :environment do
|
|
5
|
+
|
|
6
|
+
# Make the test database at the same time as the development one, if it exists
|
|
7
|
+
if Rails.env.development?
|
|
8
|
+
ActiveShard.config.shard_definitions( :test ).each do |definition|
|
|
9
|
+
create_database(definition)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
ActiveShard.config.shard_definitions( Rails.env.to_sym ).each do |definition|
|
|
13
|
+
create_database( definition )
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_database( definition )
|
|
18
|
+
begin
|
|
19
|
+
if definition.connection_adapter =~ /sqlite/
|
|
20
|
+
active_shard_does_not_implement!( definition.connection_adapter )
|
|
21
|
+
else
|
|
22
|
+
pool = ActiveShard::ActiveRecord::ConnectionProxyPool.new( definition )
|
|
23
|
+
pool.connection
|
|
24
|
+
end
|
|
25
|
+
rescue
|
|
26
|
+
case definition.connection_adapter
|
|
27
|
+
when /mysql/
|
|
28
|
+
@charset = ENV['CHARSET'] || 'utf8'
|
|
29
|
+
@collation = ENV['COLLATION'] || 'utf8_unicode_ci'
|
|
30
|
+
creation_options = {:charset => (definition.connection_spec['charset'] || @charset), :collation => (definition.connection_spec['collation'] || @collation)}
|
|
31
|
+
error_class = definition.connection_adapter =~ /mysql2/ ? Mysql2::Error : Mysql::Error
|
|
32
|
+
access_denied_error = 1045
|
|
33
|
+
begin
|
|
34
|
+
sd = ActiveShard::ShardDefinition.new(
|
|
35
|
+
definition.name, { :schema => definition.schema }.merge( definition.connection_spec ).merge( :database => nil )
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
pool = ActiveShard::ActiveRecord::ConnectionProxyPool.new( sd )
|
|
39
|
+
|
|
40
|
+
pool.connection.create_database( definition.connection_database, creation_options )
|
|
41
|
+
|
|
42
|
+
ActiveShard::ActiveRecord::ConnectionProxyPool.new( definition ).connection
|
|
43
|
+
rescue error_class => sqlerr
|
|
44
|
+
$stderr.puts sqlerr.error
|
|
45
|
+
$stderr.puts "Couldn't create database for #{definition.inspect}"
|
|
46
|
+
end
|
|
47
|
+
when 'postgresql'
|
|
48
|
+
active_shard_does_not_implement!( 'postgresql' )
|
|
49
|
+
end
|
|
50
|
+
else
|
|
51
|
+
$stderr.puts "#{definition.connection_database} already exists"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
desc "Migrate the database (options: VERSION=x, VERBOSE=false)."
|
|
56
|
+
task :migrate, [:shard_name] => :environment do |t, args|
|
|
57
|
+
schemas = {}
|
|
58
|
+
|
|
59
|
+
active_shard_definitions( args ).each do |shard_definition|
|
|
60
|
+
with_shard( shard_definition.name ) do |shard_name, schema|
|
|
61
|
+
schemas[schema] = shard_name
|
|
62
|
+
|
|
63
|
+
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
|
64
|
+
ActiveRecord::Migrator.migrate("db/migrate/#{schema}/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
schemas.each_pair { |schema, shard| dump_schema( shard ) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
namespace :migrate do
|
|
72
|
+
# desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
|
|
73
|
+
task :redo, [:shard_name] => :environment do |t, args|
|
|
74
|
+
if ENV["VERSION"]
|
|
75
|
+
Rake::Task["shards:migrate:down"].invoke( *args.values )
|
|
76
|
+
Rake::Task["shards:migrate:up"].invoke( *args.values )
|
|
77
|
+
else
|
|
78
|
+
Rake::Task["shards:rollback"].invoke( *args.values )
|
|
79
|
+
Rake::Task["shards:migrate"].invoke( *args.values )
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# desc 'Runs the "up" for a given migration VERSION.'
|
|
84
|
+
task :up, [:shard_name] => :environment do |t, args|
|
|
85
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
|
86
|
+
raise "VERSION is required" unless version
|
|
87
|
+
|
|
88
|
+
with_shard( args ) do |shard_name, schema|
|
|
89
|
+
ActiveRecord::Migrator.run(:up, "db/migrate/#{schema}", version)
|
|
90
|
+
|
|
91
|
+
dump_schema( shard_name )
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# desc 'Runs the "down" for a given migration VERSION.'
|
|
96
|
+
task :down, [:shard_name] => :environment do |t, args|
|
|
97
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
|
98
|
+
raise "VERSION is required" unless version
|
|
99
|
+
|
|
100
|
+
with_shard( args ) do |shard_name, schema|
|
|
101
|
+
ActiveRecord::Migrator.run(:down, "db/migrate/#{schema}", version)
|
|
102
|
+
|
|
103
|
+
dump_schema( shard_name )
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
|
|
109
|
+
task :rollback, [:shard_name] => :environment do |t, args|
|
|
110
|
+
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
|
|
111
|
+
|
|
112
|
+
with_shard( args ) do |shard_name, schema|
|
|
113
|
+
ActiveRecord::Migrator.rollback("db/migrate/#{schema}", step)
|
|
114
|
+
|
|
115
|
+
dump_schema( shard_name )
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
|
|
120
|
+
task :forward, [:shard_name] => :environment do |t, args|
|
|
121
|
+
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
|
|
122
|
+
|
|
123
|
+
with_shard( args ) do |shard_name, schema|
|
|
124
|
+
ActiveRecord::Migrator.forward("db/migrate/#{schema}", step)
|
|
125
|
+
|
|
126
|
+
dump_schema( shard_name )
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
desc "Retrieves the current schema version number"
|
|
131
|
+
task :version, [:shard_name] => :environment do |t, args|
|
|
132
|
+
with_shard( args ) do |shard_name, schema|
|
|
133
|
+
puts "Current version: #{ActiveRecord::Migrator.current_version}"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
namespace :schema do
|
|
138
|
+
|
|
139
|
+
desc "Create a db/<schema>_schema.rb file that can be portably used against any DB supported by AR"
|
|
140
|
+
task :dump, [:shard_name] => :environment do |t, args|
|
|
141
|
+
require 'active_record/schema_dumper'
|
|
142
|
+
|
|
143
|
+
defs = active_shard_definitions( args )
|
|
144
|
+
|
|
145
|
+
defs.schemas.each do |schema|
|
|
146
|
+
shard_definition = defs.by_schema( schema ).first
|
|
147
|
+
|
|
148
|
+
with_shard( shard_definition.name ) do
|
|
149
|
+
File.open( "#{Rails.root}/db/#{schema}_schema.rb", "w" ) do |file|
|
|
150
|
+
ActiveRecord::SchemaDumper.dump( ActiveRecord::Base.connection, file )
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
Rake::Task["shards:schema:dump"].reenable
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
desc "Load a <schema>_schema.rb file into the database"
|
|
159
|
+
task :load, [:shard_name] => :environment do |t, args|
|
|
160
|
+
defs = active_shard_definitions( args )
|
|
161
|
+
|
|
162
|
+
defs.each do |shard_definition|
|
|
163
|
+
with_shard( shard_definition.name ) do
|
|
164
|
+
ActiveRecord::Schema.class_eval <<-EOM
|
|
165
|
+
def self.migrations_path
|
|
166
|
+
"db/migrate/#{shard_definition.schema}"
|
|
167
|
+
end
|
|
168
|
+
EOM
|
|
169
|
+
|
|
170
|
+
file = "#{Rails.root}/db/#{shard_definition.schema}_schema.rb"
|
|
171
|
+
if File.exists?( file )
|
|
172
|
+
load( file )
|
|
173
|
+
else
|
|
174
|
+
abort %{#{file} doesn't exist yet. Run "rake shards:migrate[#{shard_definition.name}]" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded}
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
namespace :structure do
|
|
182
|
+
desc "Dump the database structure to an SQL file"
|
|
183
|
+
task :dump, [:shard_name] => :environment do |t, args|
|
|
184
|
+
ActiveShard.with_environment( :development ) do
|
|
185
|
+
defs = active_shard_definitions( args )
|
|
186
|
+
|
|
187
|
+
defs.schemas.each do |schema|
|
|
188
|
+
shard_definition = defs.by_schema( schema ).first
|
|
189
|
+
|
|
190
|
+
with_shard( shard_definition.name ) do
|
|
191
|
+
|
|
192
|
+
structure_file_path = "#{Rails.root}/db/#{schema}_structure.sql"
|
|
193
|
+
|
|
194
|
+
abcs = ActiveShard.shard( shard_definition.name ).connection_adapter
|
|
195
|
+
case abcs
|
|
196
|
+
when /mysql/, "oci", "oracle"
|
|
197
|
+
# We are already connected via with_shard, so just use.
|
|
198
|
+
#
|
|
199
|
+
File.open( structure_file_path, "w+" ) { |f| f << ActiveRecord::Base.connection.structure_dump }
|
|
200
|
+
when "postgresql", "sqlite", "sqlite3", "sqlserver", "firebird"
|
|
201
|
+
active_shard_does_not_implement!(abcs)
|
|
202
|
+
else
|
|
203
|
+
raise "Task not supported by '#{abcs}'"
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
if ActiveRecord::Base.connection.supports_migrations?
|
|
207
|
+
File.open( structure_file_path, "a" ) { |f| f << ActiveRecord::Base.connection.dump_schema_information }
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
namespace :test do
|
|
216
|
+
# desc "Recreate the test database from the current schema.rb"
|
|
217
|
+
task :load => 'shards:test:purge' do
|
|
218
|
+
ActiveShard.with_environment( :test ) do
|
|
219
|
+
ActiveRecord::Schema.verbose = false
|
|
220
|
+
|
|
221
|
+
puts "Building test shards ..."
|
|
222
|
+
ActiveShard.shard_definitions.each do |shard_definition|
|
|
223
|
+
puts " --> #{shard_definition.name} (#{shard_definition.schema})"
|
|
224
|
+
Rake::Task["shards:schema:load"].invoke( shard_definition.name )
|
|
225
|
+
Rake::Task["shards:schema:load"].reenable
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# desc "Recreate the test database from the current environment's database schema"
|
|
231
|
+
task :clone => %w(shards:schema:dump shards:test:load)
|
|
232
|
+
|
|
233
|
+
# desc "Recreate the test databases from the development structure"
|
|
234
|
+
task :clone_structure, [:shard_name] => [ "shards:structure:dump", "shards:test:purge" ] do |t, args|
|
|
235
|
+
ActiveShard.with_environment( :test ) do
|
|
236
|
+
defs = active_shard_definitions( args )
|
|
237
|
+
|
|
238
|
+
defs.each do |shard_definition|
|
|
239
|
+
adapter = shard_definition.connection_adapter
|
|
240
|
+
|
|
241
|
+
case adapter
|
|
242
|
+
when /mysql/
|
|
243
|
+
with_shard( shard_definition.name ) do
|
|
244
|
+
ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
|
|
245
|
+
IO.readlines("#{Rails.root}/db/#{shard_definition.schema}_structure.sql").join.split("\n\n").each do |table|
|
|
246
|
+
ActiveRecord::Base.connection.execute(table)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
when "postgresql", "sqlite", "sqlite3", "sqlserver", "oci", "oracle", "firebird"
|
|
250
|
+
active_shard_does_not_implement!( adapter )
|
|
251
|
+
else
|
|
252
|
+
raise "Task not supported by '#{adapter}'"
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# desc "Empty the test database"
|
|
259
|
+
task :purge => :environment do
|
|
260
|
+
ActiveShard.with_environment( :test ) do
|
|
261
|
+
ActiveShard.shard_definitions.each do |shard_definition|
|
|
262
|
+
with_shard( shard_definition.name ) do |shard_name, schema|
|
|
263
|
+
adapter = ActiveShard.shard( shard_name ).connection_adapter
|
|
264
|
+
|
|
265
|
+
case adapter
|
|
266
|
+
when /mysql/
|
|
267
|
+
ActiveRecord::Base.connection.recreate_database(
|
|
268
|
+
shard_definition.connection_database,
|
|
269
|
+
shard_definition.connection_spec
|
|
270
|
+
)
|
|
271
|
+
when "postgresql", "sqlite", "sqlite3", "sqlserver", "oci", "oracle", "firebird"
|
|
272
|
+
active_shard_does_not_implement!( adapter )
|
|
273
|
+
else
|
|
274
|
+
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# desc 'Check for pending migrations and load the test schema'
|
|
282
|
+
task :prepare => :environment do
|
|
283
|
+
clone_schema
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def dump_schema( *args )
|
|
289
|
+
Rake::Task[{ :sql => "shards:structure:dump", :ruby => "shards:schema:dump" }[ActiveRecord::Base.schema_format]].invoke(*args)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def clone_schema( *args )
|
|
293
|
+
Rake::Task[{ :sql => "shards:test:clone_structure", :ruby => "shards:test:load" }[ActiveRecord::Base.schema_format]].invoke(*args)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def active_shard_does_not_implement!( adapter )
|
|
297
|
+
raise "Unimplemented by ActiveShard at the moment. If someone using #{adapter} wants to fix this, that would be awesome!"
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def active_shard_definitions( options={} )
|
|
301
|
+
shard_name = options[ :shard_name ]
|
|
302
|
+
|
|
303
|
+
if shard_name.blank?
|
|
304
|
+
ActiveShard.shard_definitions
|
|
305
|
+
else
|
|
306
|
+
ActiveShard::ShardCollection.new([ ActiveShard.shard( shard_name ) ])
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def with_shard( args )
|
|
311
|
+
shard_name =
|
|
312
|
+
case args
|
|
313
|
+
when Symbol, String
|
|
314
|
+
args.to_sym
|
|
315
|
+
else
|
|
316
|
+
args[ :shard_name ].nil? ? nil : args[ :shard_name ].to_sym
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
raise "No shard specified. Please run with shard name, rake task[shard_name]" unless shard_name
|
|
320
|
+
|
|
321
|
+
schema = ActiveShard.shard( shard_name ).schema.to_sym
|
|
322
|
+
|
|
323
|
+
ActiveRecord::Base.send( :include, ActiveShard::ActiveRecord::ShardSupport )
|
|
324
|
+
ActiveRecord::Base.schema_name( schema )
|
|
325
|
+
|
|
326
|
+
ActiveShard.with( shard_name ) do
|
|
327
|
+
yield( shard_name, schema )
|
|
328
|
+
end
|
|
329
|
+
end
|
data/lib/active_shard/version.rb
CHANGED
metadata
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: active_shard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease:
|
|
5
|
-
version: 0.2.
|
|
5
|
+
version: 0.2.3
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- Brasten Sager
|
|
@@ -45,6 +45,7 @@ files:
|
|
|
45
45
|
- lib/active_shard/active_record.rb
|
|
46
46
|
- lib/active_shard/config.rb
|
|
47
47
|
- lib/active_shard/exceptions.rb
|
|
48
|
+
- lib/active_shard/rails/database.rake
|
|
48
49
|
- lib/active_shard/railtie.rb
|
|
49
50
|
- lib/active_shard/scope.rb
|
|
50
51
|
- lib/active_shard/scope_manager.rb
|