activerecord 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (181) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +2102 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +35 -44
  5. data/examples/performance.rb +110 -100
  6. data/lib/active_record/aggregations.rb +59 -75
  7. data/lib/active_record/associations/alias_tracker.rb +76 -0
  8. data/lib/active_record/associations/association.rb +248 -0
  9. data/lib/active_record/associations/association_scope.rb +135 -0
  10. data/lib/active_record/associations/belongs_to_association.rb +60 -59
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -59
  12. data/lib/active_record/associations/builder/association.rb +108 -0
  13. data/lib/active_record/associations/builder/belongs_to.rb +98 -0
  14. data/lib/active_record/associations/builder/collection_association.rb +89 -0
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
  16. data/lib/active_record/associations/builder/has_many.rb +15 -0
  17. data/lib/active_record/associations/builder/has_one.rb +25 -0
  18. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  19. data/lib/active_record/associations/collection_association.rb +608 -0
  20. data/lib/active_record/associations/collection_proxy.rb +986 -0
  21. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +40 -112
  22. data/lib/active_record/associations/has_many_association.rb +83 -76
  23. data/lib/active_record/associations/has_many_through_association.rb +147 -66
  24. data/lib/active_record/associations/has_one_association.rb +67 -108
  25. data/lib/active_record/associations/has_one_through_association.rb +21 -25
  26. data/lib/active_record/associations/join_dependency/join_association.rb +174 -0
  27. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  28. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  29. data/lib/active_record/associations/join_dependency.rb +235 -0
  30. data/lib/active_record/associations/join_helper.rb +45 -0
  31. data/lib/active_record/associations/preloader/association.rb +121 -0
  32. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  33. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  35. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  36. data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
  37. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  38. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  39. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  40. data/lib/active_record/associations/preloader/through_association.rb +63 -0
  41. data/lib/active_record/associations/preloader.rb +178 -0
  42. data/lib/active_record/associations/singular_association.rb +64 -0
  43. data/lib/active_record/associations/through_association.rb +87 -0
  44. data/lib/active_record/associations.rb +512 -1224
  45. data/lib/active_record/attribute_assignment.rb +201 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +49 -12
  47. data/lib/active_record/attribute_methods/dirty.rb +51 -28
  48. data/lib/active_record/attribute_methods/primary_key.rb +94 -22
  49. data/lib/active_record/attribute_methods/query.rb +5 -4
  50. data/lib/active_record/attribute_methods/read.rb +63 -72
  51. data/lib/active_record/attribute_methods/serialization.rb +162 -0
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -41
  53. data/lib/active_record/attribute_methods/write.rb +39 -13
  54. data/lib/active_record/attribute_methods.rb +362 -29
  55. data/lib/active_record/autosave_association.rb +132 -75
  56. data/lib/active_record/base.rb +83 -1627
  57. data/lib/active_record/callbacks.rb +69 -47
  58. data/lib/active_record/coders/yaml_column.rb +38 -0
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +411 -138
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +21 -11
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -173
  62. data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -22
  63. data/lib/active_record/connection_adapters/abstract/quoting.rb +82 -25
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +176 -414
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +562 -232
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +281 -53
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
  70. data/lib/active_record/connection_adapters/column.rb +318 -0
  71. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
  73. data/lib/active_record/connection_adapters/mysql_adapter.rb +365 -450
  74. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  75. data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
  76. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  80. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
  81. data/lib/active_record/connection_adapters/postgresql_adapter.rb +672 -752
  82. data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
  83. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +588 -17
  84. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  85. data/lib/active_record/connection_handling.rb +98 -0
  86. data/lib/active_record/core.rb +463 -0
  87. data/lib/active_record/counter_cache.rb +108 -101
  88. data/lib/active_record/dynamic_matchers.rb +131 -0
  89. data/lib/active_record/errors.rb +54 -13
  90. data/lib/active_record/explain.rb +38 -0
  91. data/lib/active_record/explain_registry.rb +30 -0
  92. data/lib/active_record/explain_subscriber.rb +29 -0
  93. data/lib/active_record/fixture_set/file.rb +55 -0
  94. data/lib/active_record/fixtures.rb +703 -785
  95. data/lib/active_record/inheritance.rb +200 -0
  96. data/lib/active_record/integration.rb +60 -0
  97. data/lib/active_record/locale/en.yml +8 -1
  98. data/lib/active_record/locking/optimistic.rb +69 -60
  99. data/lib/active_record/locking/pessimistic.rb +34 -12
  100. data/lib/active_record/log_subscriber.rb +40 -6
  101. data/lib/active_record/migration/command_recorder.rb +164 -0
  102. data/lib/active_record/migration/join_table.rb +15 -0
  103. data/lib/active_record/migration.rb +614 -216
  104. data/lib/active_record/model_schema.rb +345 -0
  105. data/lib/active_record/nested_attributes.rb +248 -119
  106. data/lib/active_record/null_relation.rb +65 -0
  107. data/lib/active_record/persistence.rb +275 -57
  108. data/lib/active_record/query_cache.rb +29 -9
  109. data/lib/active_record/querying.rb +62 -0
  110. data/lib/active_record/railtie.rb +135 -21
  111. data/lib/active_record/railties/console_sandbox.rb +5 -0
  112. data/lib/active_record/railties/controller_runtime.rb +17 -5
  113. data/lib/active_record/railties/databases.rake +249 -359
  114. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  115. data/lib/active_record/readonly_attributes.rb +30 -0
  116. data/lib/active_record/reflection.rb +283 -103
  117. data/lib/active_record/relation/batches.rb +38 -34
  118. data/lib/active_record/relation/calculations.rb +252 -139
  119. data/lib/active_record/relation/delegation.rb +125 -0
  120. data/lib/active_record/relation/finder_methods.rb +182 -188
  121. data/lib/active_record/relation/merger.rb +161 -0
  122. data/lib/active_record/relation/predicate_builder.rb +86 -21
  123. data/lib/active_record/relation/query_methods.rb +917 -134
  124. data/lib/active_record/relation/spawn_methods.rb +53 -92
  125. data/lib/active_record/relation.rb +405 -143
  126. data/lib/active_record/result.rb +67 -0
  127. data/lib/active_record/runtime_registry.rb +17 -0
  128. data/lib/active_record/sanitization.rb +168 -0
  129. data/lib/active_record/schema.rb +20 -14
  130. data/lib/active_record/schema_dumper.rb +55 -46
  131. data/lib/active_record/schema_migration.rb +39 -0
  132. data/lib/active_record/scoping/default.rb +146 -0
  133. data/lib/active_record/scoping/named.rb +175 -0
  134. data/lib/active_record/scoping.rb +82 -0
  135. data/lib/active_record/serialization.rb +8 -46
  136. data/lib/active_record/serializers/xml_serializer.rb +21 -68
  137. data/lib/active_record/statement_cache.rb +26 -0
  138. data/lib/active_record/store.rb +156 -0
  139. data/lib/active_record/tasks/database_tasks.rb +203 -0
  140. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  141. data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
  142. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  143. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  144. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  145. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  146. data/lib/active_record/test_case.rb +57 -28
  147. data/lib/active_record/timestamp.rb +49 -18
  148. data/lib/active_record/transactions.rb +106 -63
  149. data/lib/active_record/translation.rb +22 -0
  150. data/lib/active_record/validations/associated.rb +25 -24
  151. data/lib/active_record/validations/presence.rb +65 -0
  152. data/lib/active_record/validations/uniqueness.rb +123 -83
  153. data/lib/active_record/validations.rb +29 -29
  154. data/lib/active_record/version.rb +7 -5
  155. data/lib/active_record.rb +83 -34
  156. data/lib/rails/generators/active_record/migration/migration_generator.rb +46 -9
  157. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
  158. data/lib/rails/generators/active_record/migration/templates/migration.rb +30 -8
  159. data/lib/rails/generators/active_record/model/model_generator.rb +15 -5
  160. data/lib/rails/generators/active_record/model/templates/model.rb +7 -2
  161. data/lib/rails/generators/active_record/model/templates/module.rb +3 -1
  162. data/lib/rails/generators/active_record.rb +4 -8
  163. metadata +163 -121
  164. data/CHANGELOG +0 -6023
  165. data/examples/associations.png +0 -0
  166. data/lib/active_record/association_preload.rb +0 -403
  167. data/lib/active_record/associations/association_collection.rb +0 -562
  168. data/lib/active_record/associations/association_proxy.rb +0 -295
  169. data/lib/active_record/associations/through_association_scope.rb +0 -154
  170. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -113
  171. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -401
  172. data/lib/active_record/dynamic_finder_match.rb +0 -53
  173. data/lib/active_record/dynamic_scope_match.rb +0 -32
  174. data/lib/active_record/named_scope.rb +0 -138
  175. data/lib/active_record/observer.rb +0 -140
  176. data/lib/active_record/session_store.rb +0 -340
  177. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -16
  178. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  179. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -2
  180. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -24
  181. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -0,0 +1,203 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class DatabaseAlreadyExists < StandardError; end # :nodoc:
4
+ class DatabaseNotSupported < StandardError; end # :nodoc:
5
+
6
+ # <tt>ActiveRecord::Tasks::DatabaseTasks</tt> is a utility class, which encapsulates
7
+ # logic behind common tasks used to manage database and migrations.
8
+ #
9
+ # The tasks defined here are used in rake tasks provided by Active Record.
10
+ #
11
+ # In order to use DatabaseTasks, a few config values need to be set. All the needed
12
+ # config values are set by Rails already, so it's necessary to do it only if you
13
+ # want to change the defaults or when you want to use Active Record outside of Rails
14
+ # (in such case after configuring the database tasks, you can also use the rake tasks
15
+ # defined in Active Record).
16
+ #
17
+ #
18
+ # The possible config values are:
19
+ #
20
+ # * +env+: current environment (like Rails.env).
21
+ # * +database_configuration+: configuration of your databases (as in +config/database.yml+).
22
+ # * +db_dir+: your +db+ directory.
23
+ # * +fixtures_path+: a path to fixtures directory.
24
+ # * +migrations_paths+: a list of paths to directories with migrations.
25
+ # * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
26
+ #
27
+ # Example usage of +DatabaseTasks+ outside Rails could look as such:
28
+ #
29
+ # include ActiveRecord::Tasks
30
+ # DatabaseTasks.database_configuration = YAML.load(File.read('my_database_config.yml'))
31
+ # DatabaseTasks.db_dir = 'db'
32
+ # # other settings...
33
+ #
34
+ # DatabaseTasks.create_current('production')
35
+ module DatabaseTasks
36
+ extend self
37
+
38
+ attr_writer :current_config
39
+ attr_accessor :database_configuration, :migrations_paths, :seed_loader, :db_dir,
40
+ :fixtures_path, :env
41
+
42
+ LOCAL_HOSTS = ['127.0.0.1', 'localhost']
43
+
44
+ def register_task(pattern, task)
45
+ @tasks ||= {}
46
+ @tasks[pattern] = task
47
+ end
48
+
49
+ register_task(/mysql/, ActiveRecord::Tasks::MySQLDatabaseTasks)
50
+ register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
51
+ register_task(/sqlite/, ActiveRecord::Tasks::SQLiteDatabaseTasks)
52
+
53
+ register_task(/firebird/, ActiveRecord::Tasks::FirebirdDatabaseTasks)
54
+ register_task(/sqlserver/, ActiveRecord::Tasks::SqlserverDatabaseTasks)
55
+ register_task(/(oci|oracle)/, ActiveRecord::Tasks::OracleDatabaseTasks)
56
+
57
+ def current_config(options = {})
58
+ options.reverse_merge! :env => env
59
+ if options.has_key?(:config)
60
+ @current_config = options[:config]
61
+ else
62
+ @current_config ||= if ENV['DATABASE_URL']
63
+ database_url_config
64
+ else
65
+ ActiveRecord::Base.configurations[options[:env]]
66
+ end
67
+ end
68
+ end
69
+
70
+ def create(*arguments)
71
+ configuration = arguments.first
72
+ class_for_adapter(configuration['adapter']).new(*arguments).create
73
+ rescue DatabaseAlreadyExists
74
+ $stderr.puts "#{configuration['database']} already exists"
75
+ rescue Exception => error
76
+ $stderr.puts error, *(error.backtrace)
77
+ $stderr.puts "Couldn't create database for #{configuration.inspect}"
78
+ end
79
+
80
+ def create_all
81
+ each_local_configuration { |configuration| create configuration }
82
+ end
83
+
84
+ def create_current(environment = env)
85
+ each_current_configuration(environment) { |configuration|
86
+ create configuration
87
+ }
88
+ ActiveRecord::Base.establish_connection environment
89
+ end
90
+
91
+ def create_database_url
92
+ create database_url_config
93
+ end
94
+
95
+ def drop(*arguments)
96
+ configuration = arguments.first
97
+ class_for_adapter(configuration['adapter']).new(*arguments).drop
98
+ rescue Exception => error
99
+ $stderr.puts error, *(error.backtrace)
100
+ $stderr.puts "Couldn't drop #{configuration['database']}"
101
+ end
102
+
103
+ def drop_all
104
+ each_local_configuration { |configuration| drop configuration }
105
+ end
106
+
107
+ def drop_current(environment = env)
108
+ each_current_configuration(environment) { |configuration|
109
+ drop configuration
110
+ }
111
+ end
112
+
113
+ def drop_database_url
114
+ drop database_url_config
115
+ end
116
+
117
+ def charset_current(environment = env)
118
+ charset ActiveRecord::Base.configurations[environment]
119
+ end
120
+
121
+ def charset(*arguments)
122
+ configuration = arguments.first
123
+ class_for_adapter(configuration['adapter']).new(*arguments).charset
124
+ end
125
+
126
+ def collation_current(environment = env)
127
+ collation ActiveRecord::Base.configurations[environment]
128
+ end
129
+
130
+ def collation(*arguments)
131
+ configuration = arguments.first
132
+ class_for_adapter(configuration['adapter']).new(*arguments).collation
133
+ end
134
+
135
+ def purge(configuration)
136
+ class_for_adapter(configuration['adapter']).new(configuration).purge
137
+ end
138
+
139
+ def structure_dump(*arguments)
140
+ configuration = arguments.first
141
+ filename = arguments.delete_at 1
142
+ class_for_adapter(configuration['adapter']).new(*arguments).structure_dump(filename)
143
+ end
144
+
145
+ def structure_load(*arguments)
146
+ configuration = arguments.first
147
+ filename = arguments.delete_at 1
148
+ class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
149
+ end
150
+
151
+ def load_seed
152
+ if seed_loader
153
+ seed_loader.load_seed
154
+ else
155
+ raise "You tried to load seed data, but no seed loader is specified. Please specify seed " +
156
+ "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" +
157
+ "Seed loader should respond to load_seed method"
158
+ end
159
+ end
160
+
161
+ private
162
+
163
+ def database_url_config
164
+ @database_url_config ||=
165
+ ConnectionAdapters::ConnectionSpecification::Resolver.new(ENV["DATABASE_URL"], {}).spec.config.stringify_keys
166
+ end
167
+
168
+ def class_for_adapter(adapter)
169
+ key = @tasks.keys.detect { |pattern| adapter[pattern] }
170
+ unless key
171
+ raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
172
+ end
173
+ @tasks[key]
174
+ end
175
+
176
+ def each_current_configuration(environment)
177
+ environments = [environment]
178
+ environments << 'test' if environment == 'development'
179
+
180
+ configurations = ActiveRecord::Base.configurations.values_at(*environments)
181
+ configurations.compact.each do |configuration|
182
+ yield configuration unless configuration['database'].blank?
183
+ end
184
+ end
185
+
186
+ def each_local_configuration
187
+ ActiveRecord::Base.configurations.each_value do |configuration|
188
+ next unless configuration['database']
189
+
190
+ if local_database?(configuration)
191
+ yield configuration
192
+ else
193
+ $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
194
+ end
195
+ end
196
+ end
197
+
198
+ def local_database?(configuration)
199
+ configuration['host'].blank? || LOCAL_HOSTS.include?(configuration['host'])
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,56 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class FirebirdDatabaseTasks # :nodoc:
4
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
5
+
6
+ def initialize(configuration)
7
+ ActiveSupport::Deprecation.warn "This database tasks were deprecated, because this tasks should be served by the 3rd party adapter."
8
+ @configuration = configuration
9
+ end
10
+
11
+ def create
12
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
13
+ end
14
+
15
+ def drop
16
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
17
+ end
18
+
19
+ def purge
20
+ establish_connection(:test)
21
+ connection.recreate_database!
22
+ end
23
+
24
+ def charset
25
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
26
+ end
27
+
28
+ def structure_dump(filename)
29
+ set_firebird_env(configuration)
30
+ db_string = firebird_db_string(configuration)
31
+ Kernel.system "isql -a #{db_string} > #{filename}"
32
+ end
33
+
34
+ def structure_load(filename)
35
+ set_firebird_env(configuration)
36
+ db_string = firebird_db_string(configuration)
37
+ Kernel.system "isql -i #{filename} #{db_string}"
38
+ end
39
+
40
+ private
41
+
42
+ def set_firebird_env(config)
43
+ ENV['ISC_USER'] = config['username'].to_s if config['username']
44
+ ENV['ISC_PASSWORD'] = config['password'].to_s if config['password']
45
+ end
46
+
47
+ def firebird_db_string(config)
48
+ FireRuby::Database.db_string_for(config.symbolize_keys)
49
+ end
50
+
51
+ def configuration
52
+ @configuration
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,143 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class MySQLDatabaseTasks # :nodoc:
4
+ DEFAULT_CHARSET = ENV['CHARSET'] || 'utf8'
5
+ DEFAULT_COLLATION = ENV['COLLATION'] || 'utf8_unicode_ci'
6
+ ACCESS_DENIED_ERROR = 1045
7
+
8
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
9
+
10
+ def initialize(configuration)
11
+ @configuration = configuration
12
+ end
13
+
14
+ def create
15
+ establish_connection configuration_without_database
16
+ connection.create_database configuration['database'], creation_options
17
+ establish_connection configuration
18
+ rescue ActiveRecord::StatementInvalid => error
19
+ if /database exists/ === error.message
20
+ raise DatabaseAlreadyExists
21
+ else
22
+ raise
23
+ end
24
+ rescue error_class => error
25
+ if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
26
+ $stdout.print error.error
27
+ establish_connection root_configuration_without_database
28
+ connection.create_database configuration['database'], creation_options
29
+ if configuration['username'] != 'root'
30
+ connection.execute grant_statement.gsub(/\s+/, ' ').strip
31
+ end
32
+ establish_connection configuration
33
+ else
34
+ $stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}"
35
+ $stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration['encoding']
36
+ end
37
+ end
38
+
39
+ def drop
40
+ establish_connection configuration
41
+ connection.drop_database configuration['database']
42
+ end
43
+
44
+ def purge
45
+ establish_connection :test
46
+ connection.recreate_database configuration['database'], creation_options
47
+ end
48
+
49
+ def charset
50
+ connection.charset
51
+ end
52
+
53
+ def collation
54
+ connection.collation
55
+ end
56
+
57
+ def structure_dump(filename)
58
+ args = prepare_command_options('mysqldump')
59
+ args.concat(["--result-file", "#{filename}"])
60
+ args.concat(["--no-data"])
61
+ args.concat(["#{configuration['database']}"])
62
+ unless Kernel.system(*args)
63
+ $stderr.puts "Could not dump the database structure. "\
64
+ "Make sure `mysqldump` is in your PATH and check the command output for warnings."
65
+ end
66
+ end
67
+
68
+ def structure_load(filename)
69
+ args = prepare_command_options('mysql')
70
+ args.concat(['--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
71
+ args.concat(["--database", "#{configuration['database']}"])
72
+ Kernel.system(*args)
73
+ end
74
+
75
+ private
76
+
77
+ def configuration
78
+ @configuration
79
+ end
80
+
81
+ def configuration_without_database
82
+ configuration.merge('database' => nil)
83
+ end
84
+
85
+ def creation_options
86
+ Hash.new.tap do |options|
87
+ options[:charset] = configuration['encoding'] if configuration.include? 'encoding'
88
+ options[:collation] = configuration['collation'] if configuration.include? 'collation'
89
+
90
+ # Set default charset only when collation isn't set.
91
+ options[:charset] ||= DEFAULT_CHARSET unless options[:collation]
92
+
93
+ # Set default collation only when charset is also default.
94
+ options[:collation] ||= DEFAULT_COLLATION if options[:charset] == DEFAULT_CHARSET
95
+ end
96
+ end
97
+
98
+ def error_class
99
+ if configuration['adapter'] =~ /jdbc/
100
+ require 'active_record/railties/jdbcmysql_error'
101
+ ArJdbcMySQL::Error
102
+ elsif defined?(Mysql2)
103
+ Mysql2::Error
104
+ elsif defined?(Mysql)
105
+ Mysql::Error
106
+ else
107
+ StandardError
108
+ end
109
+ end
110
+
111
+ def grant_statement
112
+ <<-SQL
113
+ GRANT ALL PRIVILEGES ON #{configuration['database']}.*
114
+ TO '#{configuration['username']}'@'localhost'
115
+ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
116
+ SQL
117
+ end
118
+
119
+ def root_configuration_without_database
120
+ configuration_without_database.merge(
121
+ 'username' => 'root',
122
+ 'password' => root_password
123
+ )
124
+ end
125
+
126
+ def root_password
127
+ $stdout.print "Please provide the root password for your mysql installation\n>"
128
+ $stdin.gets.strip
129
+ end
130
+
131
+ def prepare_command_options(command)
132
+ args = [command]
133
+ args.concat(['--user', configuration['username']]) if configuration['username']
134
+ args << "--password=#{configuration['password']}" if configuration['password']
135
+ args.concat(['--default-character-set', configuration['encoding']]) if configuration['encoding']
136
+ configuration.slice('host', 'port', 'socket').each do |k, v|
137
+ args.concat([ "--#{k}", v ]) if v
138
+ end
139
+ args
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,45 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class OracleDatabaseTasks # :nodoc:
4
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
5
+
6
+ def initialize(configuration)
7
+ ActiveSupport::Deprecation.warn "This database tasks were deprecated, because this tasks should be served by the 3rd party adapter."
8
+ @configuration = configuration
9
+ end
10
+
11
+ def create
12
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
13
+ end
14
+
15
+ def drop
16
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
17
+ end
18
+
19
+ def purge
20
+ establish_connection(:test)
21
+ connection.structure_drop.split(";\n\n").each { |ddl| connection.execute(ddl) }
22
+ end
23
+
24
+ def charset
25
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
26
+ end
27
+
28
+ def structure_dump(filename)
29
+ establish_connection(configuration)
30
+ File.open(filename, "w:utf-8") { |f| f << connection.structure_dump }
31
+ end
32
+
33
+ def structure_load(filename)
34
+ establish_connection(configuration)
35
+ IO.read(filename).split(";\n\n").each { |ddl| connection.execute(ddl) }
36
+ end
37
+
38
+ private
39
+
40
+ def configuration
41
+ @configuration
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,90 @@
1
+ require 'shellwords'
2
+
3
+ module ActiveRecord
4
+ module Tasks # :nodoc:
5
+ class PostgreSQLDatabaseTasks # :nodoc:
6
+ DEFAULT_ENCODING = ENV['CHARSET'] || 'utf8'
7
+
8
+ delegate :connection, :establish_connection, :clear_active_connections!,
9
+ to: ActiveRecord::Base
10
+
11
+ def initialize(configuration)
12
+ @configuration = configuration
13
+ end
14
+
15
+ def create(master_established = false)
16
+ establish_master_connection unless master_established
17
+ connection.create_database configuration['database'],
18
+ configuration.merge('encoding' => encoding)
19
+ establish_connection configuration
20
+ rescue ActiveRecord::StatementInvalid => error
21
+ if /database .* already exists/ === error.message
22
+ raise DatabaseAlreadyExists
23
+ else
24
+ raise
25
+ end
26
+ end
27
+
28
+ def drop
29
+ establish_master_connection
30
+ connection.drop_database configuration['database']
31
+ end
32
+
33
+ def charset
34
+ connection.encoding
35
+ end
36
+
37
+ def collation
38
+ connection.collation
39
+ end
40
+
41
+ def purge
42
+ clear_active_connections!
43
+ drop
44
+ create true
45
+ end
46
+
47
+ def structure_dump(filename)
48
+ set_psql_env
49
+ search_path = configuration['schema_search_path']
50
+ unless search_path.blank?
51
+ search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ")
52
+ end
53
+
54
+ command = "pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}"
55
+ raise 'Error dumping database' unless Kernel.system(command)
56
+
57
+ File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" }
58
+ end
59
+
60
+ def structure_load(filename)
61
+ set_psql_env
62
+ Kernel.system("psql -q -f #{filename} #{configuration['database']}")
63
+ end
64
+
65
+ private
66
+
67
+ def configuration
68
+ @configuration
69
+ end
70
+
71
+ def encoding
72
+ configuration['encoding'] || DEFAULT_ENCODING
73
+ end
74
+
75
+ def establish_master_connection
76
+ establish_connection configuration.merge(
77
+ 'database' => 'postgres',
78
+ 'schema_search_path' => 'public'
79
+ )
80
+ end
81
+
82
+ def set_psql_env
83
+ ENV['PGHOST'] = configuration['host'] if configuration['host']
84
+ ENV['PGPORT'] = configuration['port'].to_s if configuration['port']
85
+ ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password']
86
+ ENV['PGUSER'] = configuration['username'].to_s if configuration['username']
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,51 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class SQLiteDatabaseTasks # :nodoc:
4
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
5
+
6
+ def initialize(configuration, root = Rails.root)
7
+ @configuration, @root = configuration, root
8
+ end
9
+
10
+ def create
11
+ raise DatabaseAlreadyExists if File.exist?(configuration['database'])
12
+
13
+ establish_connection configuration
14
+ connection
15
+ end
16
+
17
+ def drop
18
+ require 'pathname'
19
+ path = Pathname.new configuration['database']
20
+ file = path.absolute? ? path.to_s : File.join(root, path)
21
+
22
+ FileUtils.rm(file) if File.exist?(file)
23
+ end
24
+ alias :purge :drop
25
+
26
+ def charset
27
+ connection.encoding
28
+ end
29
+
30
+ def structure_dump(filename)
31
+ dbfile = configuration['database']
32
+ `sqlite3 #{dbfile} .schema > #{filename}`
33
+ end
34
+
35
+ def structure_load(filename)
36
+ dbfile = configuration['database']
37
+ `sqlite3 #{dbfile} < "#{filename}"`
38
+ end
39
+
40
+ private
41
+
42
+ def configuration
43
+ @configuration
44
+ end
45
+
46
+ def root
47
+ @root
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,48 @@
1
+ require 'shellwords'
2
+
3
+ module ActiveRecord
4
+ module Tasks # :nodoc:
5
+ class SqlserverDatabaseTasks # :nodoc:
6
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
7
+
8
+ def initialize(configuration)
9
+ ActiveSupport::Deprecation.warn "This database tasks were deprecated, because this tasks should be served by the 3rd party adapter."
10
+ @configuration = configuration
11
+ end
12
+
13
+ def create
14
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
15
+ end
16
+
17
+ def drop
18
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
19
+ end
20
+
21
+ def purge
22
+ test = configuration.deep_dup
23
+ test_database = test['database']
24
+ test['database'] = 'master'
25
+ establish_connection(test)
26
+ connection.recreate_database!(test_database)
27
+ end
28
+
29
+ def charset
30
+ $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
31
+ end
32
+
33
+ def structure_dump(filename)
34
+ Kernel.system("smoscript -s #{configuration['host']} -d #{configuration['database']} -u #{configuration['username']} -p #{configuration['password']} -f #{filename} -A -U")
35
+ end
36
+
37
+ def structure_load(filename)
38
+ Kernel.system("sqlcmd -S #{configuration['host']} -d #{configuration['database']} -U #{configuration['username']} -P #{configuration['password']} -i #{filename}")
39
+ end
40
+
41
+ private
42
+
43
+ def configuration
44
+ @configuration
45
+ end
46
+ end
47
+ end
48
+ end