activerecord-jdbc-adapter 1.3.0.beta1 → 1.3.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. data/.gitignore +12 -11
  2. data/.travis.yml +36 -7
  3. data/Appraisals +3 -3
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +13 -6
  6. data/History.txt +64 -0
  7. data/README.md +8 -1
  8. data/Rakefile +3 -1
  9. data/gemfiles/rails23.gemfile +1 -1
  10. data/gemfiles/rails23.gemfile.lock +6 -5
  11. data/gemfiles/rails30.gemfile +1 -1
  12. data/gemfiles/rails30.gemfile.lock +7 -6
  13. data/gemfiles/rails31.gemfile +1 -1
  14. data/gemfiles/rails31.gemfile.lock +6 -5
  15. data/gemfiles/rails32.gemfile +1 -1
  16. data/gemfiles/rails32.gemfile.lock +6 -5
  17. data/gemfiles/rails40.gemfile +2 -4
  18. data/gemfiles/rails40.gemfile.lock +37 -51
  19. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  20. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -1
  21. data/lib/arel/visitors/db2.rb +5 -1
  22. data/lib/arel/visitors/hsqldb.rb +1 -0
  23. data/lib/arel/visitors/sql_server.rb +55 -13
  24. data/lib/arjdbc/db2/adapter.rb +197 -227
  25. data/lib/arjdbc/db2/as400.rb +124 -0
  26. data/lib/arjdbc/db2/connection_methods.rb +20 -1
  27. data/lib/arjdbc/derby/adapter.rb +17 -85
  28. data/lib/arjdbc/derby/connection_methods.rb +2 -1
  29. data/lib/arjdbc/discover.rb +55 -47
  30. data/lib/arjdbc/h2/adapter.rb +52 -18
  31. data/lib/arjdbc/h2/connection_methods.rb +10 -2
  32. data/lib/arjdbc/hsqldb/adapter.rb +33 -9
  33. data/lib/arjdbc/hsqldb/connection_methods.rb +10 -2
  34. data/lib/arjdbc/informix.rb +2 -1
  35. data/lib/arjdbc/jdbc.rb +5 -1
  36. data/lib/arjdbc/jdbc/adapter.rb +167 -89
  37. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  38. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  39. data/lib/arjdbc/jdbc/base_ext.rb +25 -3
  40. data/lib/arjdbc/jdbc/callbacks.rb +9 -8
  41. data/lib/arjdbc/jdbc/column.rb +8 -20
  42. data/lib/arjdbc/jdbc/connection.rb +69 -80
  43. data/lib/arjdbc/jdbc/extension.rb +6 -8
  44. data/lib/arjdbc/jdbc/jdbc.rake +3 -141
  45. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
  46. data/lib/arjdbc/mssql/adapter.rb +108 -34
  47. data/lib/arjdbc/mssql/connection_methods.rb +3 -1
  48. data/lib/arjdbc/mssql/limit_helpers.rb +3 -2
  49. data/lib/arjdbc/mssql/lock_helpers.rb +5 -1
  50. data/lib/arjdbc/mysql/adapter.rb +127 -70
  51. data/lib/arjdbc/mysql/connection_methods.rb +5 -2
  52. data/lib/arjdbc/oracle/adapter.rb +124 -94
  53. data/lib/arjdbc/oracle/connection_methods.rb +2 -1
  54. data/lib/arjdbc/postgresql/adapter.rb +99 -67
  55. data/lib/arjdbc/postgresql/column_cast.rb +3 -5
  56. data/lib/arjdbc/postgresql/connection_methods.rb +6 -6
  57. data/lib/arjdbc/railtie.rb +3 -1
  58. data/lib/arjdbc/sqlite3/adapter.rb +60 -43
  59. data/lib/arjdbc/sqlite3/connection_methods.rb +9 -9
  60. data/lib/arjdbc/sybase.rb +1 -1
  61. data/lib/arjdbc/tasks.rb +13 -0
  62. data/lib/arjdbc/tasks/database_tasks.rb +50 -0
  63. data/lib/arjdbc/tasks/databases.rake +89 -0
  64. data/lib/arjdbc/tasks/databases3.rake +203 -0
  65. data/lib/arjdbc/tasks/databases4.rake +39 -0
  66. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  67. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  68. data/lib/arjdbc/tasks/h2_database_tasks.rb +29 -0
  69. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  70. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +122 -0
  71. data/lib/arjdbc/tasks/mssql_database_tasks.rb +36 -0
  72. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
  73. data/lib/arjdbc/tasks/oracle_database_tasks.rb +62 -0
  74. data/lib/arjdbc/version.rb +1 -1
  75. data/pom.xml +11 -12
  76. data/rails_generators/jdbc_generator.rb +1 -1
  77. data/rails_generators/templates/config/initializers/jdbc.rb +8 -5
  78. data/rails_generators/templates/lib/tasks/jdbc.rake +7 -4
  79. data/rakelib/02-test.rake +42 -15
  80. data/rakelib/compile.rake +29 -2
  81. data/rakelib/db.rake +2 -1
  82. data/rakelib/rails.rake +23 -6
  83. data/src/java/arjdbc/ArJdbcModule.java +175 -0
  84. data/src/java/arjdbc/db2/DB2Module.java +2 -1
  85. data/src/java/arjdbc/derby/DerbyModule.java +5 -24
  86. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +3 -2
  87. data/src/java/arjdbc/jdbc/AdapterJavaService.java +3 -46
  88. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1001 -259
  89. data/src/java/arjdbc/mssql/MSSQLModule.java +2 -1
  90. data/src/java/arjdbc/mysql/MySQLModule.java +4 -3
  91. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -7
  92. data/src/java/arjdbc/oracle/OracleModule.java +2 -1
  93. data/src/java/arjdbc/sqlite3/SQLite3Module.java +2 -1
  94. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +12 -0
  95. data/test/db/db2.rb +14 -7
  96. data/test/db/db2/rake_test.rb +82 -0
  97. data/test/db/db2/rake_test_data.sql +35 -0
  98. data/test/db/db2/simple_test.rb +20 -0
  99. data/test/db/db2/unit_test.rb +3 -1
  100. data/test/db/derby.rb +7 -5
  101. data/test/db/derby/rake_test.rb +96 -0
  102. data/test/db/derby/simple_test.rb +10 -2
  103. data/test/db/h2.rb +6 -8
  104. data/test/db/h2/identity_column_test.rb +35 -0
  105. data/test/db/h2/offset_test.rb +49 -0
  106. data/test/db/h2/rake_test.rb +98 -0
  107. data/test/db/h2/schema_dump_test.rb +5 -1
  108. data/test/db/hsqldb.rb +6 -10
  109. data/test/db/hsqldb/rake_test.rb +101 -0
  110. data/test/db/hsqldb/schema_dump_test.rb +5 -1
  111. data/test/db/hsqldb/simple_test.rb +8 -0
  112. data/test/db/jndi_config.rb +1 -3
  113. data/test/db/jndi_pooled_config.rb +1 -3
  114. data/test/db/mssql/limit_offset_test.rb +23 -14
  115. data/test/db/mssql/rake_test.rb +143 -0
  116. data/test/db/mysql/_rails_test_mysql.32.out +1069 -1252
  117. data/test/db/mysql/nonstandard_primary_key_test.rb +21 -24
  118. data/test/db/mysql/rake_test.rb +97 -0
  119. data/test/db/mysql/schema_dump_test.rb +11 -11
  120. data/test/db/mysql/simple_test.rb +52 -3
  121. data/test/db/mysql/statement_escaping_test.rb +46 -0
  122. data/test/db/oracle/rake_test.rb +100 -0
  123. data/test/db/oracle/simple_test.rb +48 -0
  124. data/test/db/postgres/_rails_test_postgres.32.out +998 -1370
  125. data/test/db/postgres/active_schema_unit_test.rb +68 -0
  126. data/test/db/postgres/connection_test.rb +10 -2
  127. data/test/db/postgres/data_types_test.rb +2 -2
  128. data/test/db/postgres/ltree_test.rb +6 -5
  129. data/test/db/postgres/native_types_test.rb +1 -5
  130. data/test/db/postgres/rake_test.rb +117 -0
  131. data/test/db/postgres/schema_dump_test.rb +9 -2
  132. data/test/db/postgres/schema_test.rb +4 -2
  133. data/test/db/postgres/simple_test.rb +57 -16
  134. data/test/db/sqlite3.rb +3 -10
  135. data/test/db/sqlite3/_rails_test_sqlite3.32.out +1070 -1298
  136. data/test/db/sqlite3/rake_test.rb +71 -0
  137. data/test/db/sqlite3/simple_test.rb +9 -9
  138. data/test/has_many_through.rb +4 -1
  139. data/test/jdbc/db2.rb +14 -1
  140. data/test/jdbc_column_test.rb +23 -0
  141. data/test/{generic_jdbc_connection_test.rb → jdbc_connection_test.rb} +22 -17
  142. data/test/jndi_callbacks_test.rb +26 -28
  143. data/test/jndi_test.rb +7 -16
  144. data/test/models/data_types.rb +2 -1
  145. data/test/models/thing.rb +1 -0
  146. data/test/rails/mysql.rb +13 -0
  147. data/test/rails/sqlite3/version.rb +6 -0
  148. data/test/rails_stub.rb +31 -0
  149. data/test/rake_test_support.rb +298 -0
  150. data/test/serialize.rb +2 -4
  151. data/test/{helper.rb → shared_helper.rb} +0 -0
  152. data/test/simple.rb +167 -93
  153. data/test/test_helper.rb +52 -16
  154. metadata +388 -354
  155. data/lib/pg.rb +0 -26
  156. data/test/abstract_db_create.rb +0 -139
  157. data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -36
  158. data/test/db/mssql/db_create_test.rb +0 -29
  159. data/test/db/mysql/db_create_test.rb +0 -33
  160. data/test/db/postgres/db_create_test.rb +0 -44
  161. data/test/db/postgres/db_drop_test.rb +0 -17
@@ -8,8 +8,8 @@ module ArJdbc
8
8
  return string unless String === string
9
9
 
10
10
  case string
11
- when 'infinity'; 1.0 / 0.0
12
- when '-infinity'; -1.0 / 0.0
11
+ when 'infinity' then 1.0 / 0.0
12
+ when '-infinity' then -1.0 / 0.0
13
13
  when / BC$/
14
14
  super("-" + string.sub(/ BC$/, ""))
15
15
  else
@@ -19,9 +19,7 @@ module ArJdbc
19
19
 
20
20
  def hstore_to_string(object)
21
21
  if Hash === object
22
- object.map { |k,v|
23
- "#{escape_hstore(k)}=>#{escape_hstore(v)}"
24
- }.join ','
22
+ object.map { |k,v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(',')
25
23
  else
26
24
  object
27
25
  end
@@ -6,17 +6,17 @@ ArJdbc::ConnectionMethods.module_eval do
6
6
  rescue LoadError # assuming driver.jar is on the class-path
7
7
  end
8
8
 
9
- config[:username] ||= Java::JavaLang::System.get_property("user.name")
10
9
  config[:host] ||= "localhost"
11
10
  config[:port] ||= 5432
11
+ config[:username] ||= Java::JavaLang::System.get_property("user.name")
12
12
  config[:url] ||= "jdbc:postgresql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
13
13
  config[:url] << config[:pg_params] if config[:pg_params]
14
14
  config[:driver] ||= defined?(::Jdbc::Postgres.driver_name) ? ::Jdbc::Postgres.driver_name : 'org.postgresql.Driver'
15
- config[:adapter_class] = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
16
- config[:adapter_spec] = ::ArJdbc::PostgreSQL
17
- conn = jdbc_connection(config)
18
- conn.execute("SET SEARCH_PATH TO #{config[:schema_search_path]}") if config[:schema_search_path]
19
- conn
15
+ config[:adapter_spec] ||= ::ArJdbc::PostgreSQL
16
+ config[:adapter_class] = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter unless config.key?(:adapter_class)
17
+ # config[:connection_alive_sql] ||= 'SELECT 1'
18
+
19
+ jdbc_connection(config)
20
20
  end
21
21
  alias_method :jdbcpostgresql_connection, :postgresql_connection
22
22
  end
@@ -3,7 +3,9 @@ require 'rails/railtie'
3
3
  module ArJdbc
4
4
  class Railtie < ::Rails::Railtie
5
5
  rake_tasks do
6
- load File.expand_path('jdbc/rake_tasks.rb', File.dirname(__FILE__))
6
+ if defined? ActiveRecord::Railtie # only if AR being used
7
+ load File.expand_path('tasks.rb', File.dirname(__FILE__))
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -1,7 +1,9 @@
1
+ ArJdbc.load_java_part :SQLite3
2
+
1
3
  require 'arjdbc/jdbc/missing_functionality_helper'
2
4
  require 'arjdbc/sqlite3/explain_support'
3
5
 
4
- module ::ArJdbc
6
+ module ArJdbc
5
7
  module SQLite3
6
8
 
7
9
  def self.column_selector
@@ -86,14 +88,21 @@ module ::ArJdbc
86
88
 
87
89
  end
88
90
 
89
- def self.arel2_visitors(config)
90
- {
91
- 'sqlite3' => ::Arel::Visitors::SQLite,
92
- 'jdbcsqlite3' => ::Arel::Visitors::SQLite
93
- }
91
+ def self.arel2_visitors(config = nil)
92
+ { 'sqlite3' => ::Arel::Visitors::SQLite, 'jdbcsqlite3' => ::Arel::Visitors::SQLite }
94
93
  end
95
94
 
96
- ADAPTER_NAME = 'SQLite'
95
+ def new_visitor(config = nil)
96
+ visitor = ::Arel::Visitors::SQLite
97
+ ( prepared_statements? ? visitor : bind_substitution(visitor) ).new(self)
98
+ end if defined? ::Arel::Visitors::SQLite
99
+
100
+ # @see #bind_substitution
101
+ class BindSubstitution < Arel::Visitors::SQLite # :nodoc:
102
+ include Arel::Visitors::BindVisitor
103
+ end if defined? Arel::Visitors::BindVisitor
104
+
105
+ ADAPTER_NAME = 'SQLite'.freeze
97
106
 
98
107
  def adapter_name # :nodoc:
99
108
  ADAPTER_NAME
@@ -200,6 +209,10 @@ module ::ArJdbc
200
209
  end
201
210
  end
202
211
 
212
+ def quote_table_name_for_assignment(table, attr)
213
+ quote_column_name(attr)
214
+ end if ::ActiveRecord::VERSION::MAJOR > 3
215
+
203
216
  def quote_column_name(name) # :nodoc:
204
217
  %Q("#{name.to_s.gsub('"', '""')}") # "' kludge for emacs font-lock
205
218
  end
@@ -235,22 +248,6 @@ module ::ArJdbc
235
248
  table_name && tables(nil, table_name).any?
236
249
  end
237
250
 
238
- IndexDefinition = ::ActiveRecord::ConnectionAdapters::IndexDefinition # :nodoc:
239
-
240
- def indexes(table_name, name = nil)
241
- result = select_rows("SELECT name, sql FROM sqlite_master" <<
242
- " WHERE tbl_name = #{quote_table_name(table_name)} AND type = 'index'", name)
243
-
244
- result.map do |row|
245
- name, index_sql = row[0], row[1]
246
- unique = !! (index_sql =~ /unique/i)
247
- columns = index_sql.match(/\((.*)\)/)[1].gsub(/,/,' ').split.map do |col|
248
- match = /^"(.+)"$/.match(col); match ? match[1] : col
249
- end
250
- IndexDefinition.new(table_name, name, unique, columns)
251
- end
252
- end
253
-
254
251
  # Returns 62. SQLite supports index names up to 64
255
252
  # characters. The rest is used by rails internally to perform
256
253
  # temporary rename operations
@@ -270,7 +267,15 @@ module ::ArJdbc
270
267
  execute("RELEASE SAVEPOINT #{current_savepoint_name}")
271
268
  end
272
269
 
273
- def recreate_database(name, options = {})
270
+ def recreate_database(name = nil, options = {}) # :nodoc:
271
+ drop_database(name)
272
+ create_database(name, options)
273
+ end
274
+
275
+ def create_database(name = nil, options = {}) # :nodoc:
276
+ end
277
+
278
+ def drop_database(name = nil) # :nodoc:
274
279
  tables.each { |table| drop_table(table) }
275
280
  end
276
281
 
@@ -308,7 +313,7 @@ module ::ArJdbc
308
313
  raise e
309
314
  end
310
315
 
311
- def jdbc_columns(table_name, name = nil) # :nodoc:
316
+ def columns(table_name, name = nil) # :nodoc:
312
317
  klass = ::ActiveRecord::ConnectionAdapters::SQLite3Column
313
318
  table_structure(table_name).map do |field|
314
319
  klass.new(field['name'], field['dflt_value'], field['type'], field['notnull'] == 0)
@@ -345,6 +350,16 @@ module ::ArJdbc
345
350
  end
346
351
  end
347
352
 
353
+ if ActiveRecord::VERSION::MAJOR >= 4
354
+
355
+ def remove_column(table_name, column_name, type = nil, options = {}) #:nodoc:
356
+ alter_table(table_name) do |definition|
357
+ definition.remove_column column_name
358
+ end
359
+ end
360
+
361
+ else
362
+
348
363
  def remove_column(table_name, *column_names) #:nodoc:
349
364
  if column_names.empty?
350
365
  raise ArgumentError.new(
@@ -359,7 +374,9 @@ module ::ArJdbc
359
374
  end
360
375
  end
361
376
  alias :remove_columns :remove_column
362
-
377
+
378
+ end
379
+
363
380
  def change_column_default(table_name, column_name, default) #:nodoc:
364
381
  alter_table(table_name) do |definition|
365
382
  definition[column_name].default = default
@@ -410,6 +427,10 @@ module ::ArJdbc
410
427
  "DEFAULT VALUES"
411
428
  end
412
429
 
430
+ def encoding
431
+ select_value 'PRAGMA encoding'
432
+ end
433
+
413
434
  protected
414
435
 
415
436
  include ArJdbc::MissingFunctionalityHelper
@@ -442,9 +463,10 @@ module ::ArJdbc
442
463
  end
443
464
 
444
465
  module ActiveRecord::ConnectionAdapters
445
- remove_const(:SQLite3Adapter) if const_defined?(:SQLite3Adapter)
446
- remove_const(:SQLiteAdapter) if const_defined?(:SQLiteAdapter)
447
466
 
467
+ # NOTE: SQLite3Column exists in native adapter since AR 4.0
468
+ remove_const(:SQLite3Column) if const_defined?(:SQLite3Column)
469
+
448
470
  class SQLite3Column < JdbcColumn
449
471
  include ArJdbc::SQLite3::Column
450
472
 
@@ -467,7 +489,9 @@ module ActiveRecord::ConnectionAdapters
467
489
  value
468
490
  end
469
491
  end
470
-
492
+
493
+ remove_const(:SQLite3Adapter) if const_defined?(:SQLite3Adapter)
494
+
471
495
  class SQLite3Adapter < JdbcAdapter
472
496
  include ArJdbc::SQLite3
473
497
  include ArJdbc::SQLite3::ExplainSupport
@@ -477,24 +501,17 @@ module ActiveRecord::ConnectionAdapters
477
501
  end
478
502
 
479
503
  def jdbc_column_class
480
- ActiveRecord::ConnectionAdapters::SQLite3Column
504
+ ::ActiveRecord::ConnectionAdapters::SQLite3Column
481
505
  end
482
-
483
- alias_chained_method :columns, :query_cache, :jdbc_columns
484
506
 
485
507
  end
486
508
 
487
- SQLiteAdapter = SQLite3Adapter
488
- end
489
-
490
- # Don't need to load native sqlite3 adapter
491
- $LOADED_FEATURES << 'active_record/connection_adapters/sqlite_adapter.rb'
492
- $LOADED_FEATURES << 'active_record/connection_adapters/sqlite3_adapter.rb'
509
+ if ActiveRecord::VERSION::MAJOR <= 3
510
+ remove_const(:SQLiteColumn) if const_defined?(:SQLiteColumn)
511
+ SQLiteColumn = SQLite3Column
512
+
513
+ remove_const(:SQLiteAdapter) if const_defined?(:SQLiteAdapter)
493
514
 
494
- # Fake out sqlite3/version driver for AR tests
495
- $LOADED_FEATURES << 'sqlite3/version.rb'
496
- module SQLite3
497
- module Version
498
- VERSION = '1.2.6' # query_cache_test.rb requires SQLite3::Version::VERSION > '1.2.5'
515
+ SQLiteAdapter = SQLite3Adapter
499
516
  end
500
517
  end
@@ -11,23 +11,23 @@ ArJdbc::ConnectionMethods.module_eval do
11
11
  database = '' if database == ':memory:'
12
12
  config[:url] ||= "jdbc:sqlite:#{database}"
13
13
  config[:driver] ||= defined?(::Jdbc::SQLite3.driver_name) ? ::Jdbc::SQLite3.driver_name : 'org.sqlite.JDBC'
14
- config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter
15
- config[:adapter_spec] = ::ArJdbc::SQLite3
14
+ config[:adapter_spec] ||= ::ArJdbc::SQLite3
15
+ config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter unless config.key?(:adapter_class)
16
+ config[:connection_alive_sql] ||= 'SELECT 1'
17
+
16
18
  jdbc_connection(config)
17
19
  end
18
20
  alias_method :jdbcsqlite3_connection, :sqlite3_connection
19
21
 
20
22
  private
23
+
21
24
  def parse_sqlite3_config!(config)
22
25
  config[:database] ||= config[:dbfile]
23
-
24
- # Allow database path relative to RAILS_ROOT, but only if
25
- # the database path is not the special path that tells
26
- # Sqlite to build a database only in memory.
27
- rails_root_defined = defined?(Rails.root) || Object.const_defined?(:RAILS_ROOT)
28
- if rails_root_defined && ':memory:' != config[:database]
26
+ # Allow database path relative to RAILS_ROOT :
27
+ if config[:database] != ':memory:' && defined?(Rails.root) || Object.const_defined?(:RAILS_ROOT)
29
28
  rails_root = defined?(Rails.root) ? Rails.root : RAILS_ROOT
30
- config[:database] = File.expand_path(config[:database], rails_root)
29
+ config[:database] = File.expand_path(config[:database], rails_root.to_s)
31
30
  end
32
31
  end
32
+
33
33
  end
data/lib/arjdbc/sybase.rb CHANGED
@@ -1,2 +1,2 @@
1
1
  require 'arjdbc'
2
- require 'arjdbc/sybase/adapter.rb'
2
+ require 'arjdbc/sybase/adapter'
@@ -0,0 +1,13 @@
1
+ if defined?(Rake.application) && Rake.application
2
+ skip = ENV["SKIP_AR_JDBC_RAKE_REDEFINES"] # jruby -J-Darjdc.tasks.skip=true -S rake ...
3
+ if ! Java::JavaLang::Boolean.getBoolean('arjdbc.tasks.skip') || ! ( skip && skip != 'false' )
4
+ databases_rake = File.expand_path('tasks/databases.rake', File.dirname(__FILE__))
5
+ if Rake.application.lookup("db:create")
6
+ load databases_rake # load the override tasks now
7
+ else # rails tasks not loaded yet; load as an import
8
+ Rake.application.add_import(databases_rake)
9
+ end
10
+ end
11
+ else
12
+ warn "ArJdbc: could not load rake tasks - rake not loaded ..."
13
+ end
@@ -0,0 +1,50 @@
1
+ module ArJdbc
2
+ module Tasks
3
+
4
+ if defined? ActiveRecord::Tasks::DatabaseTasks # AR-4.x
5
+
6
+ def self.register_tasks(pattern, task)
7
+ ActiveRecord::Tasks::DatabaseTasks.register_task(pattern, task)
8
+ end
9
+
10
+ else
11
+
12
+ @@tasks = {}
13
+
14
+ def self.register_tasks(pattern, task)
15
+ @@tasks[pattern] = task
16
+ end
17
+
18
+ def self.tasks_instance(config)
19
+ adapter = config['adapter']
20
+ key = @@tasks.keys.detect { |pattern| adapter[pattern] }
21
+ ( @@tasks[key] || JdbcDatabaseTasks ).new(config)
22
+ end
23
+
24
+ end
25
+
26
+ require 'arjdbc/tasks/jdbc_database_tasks'
27
+ require 'arjdbc/tasks/db2_database_tasks'
28
+ require 'arjdbc/tasks/derby_database_tasks'
29
+ require 'arjdbc/tasks/h2_database_tasks'
30
+ require 'arjdbc/tasks/hsqldb_database_tasks'
31
+ require 'arjdbc/tasks/mssql_database_tasks'
32
+ require 'arjdbc/tasks/oracle_database_tasks'
33
+
34
+ # re-invent built-in (but deprecated on 4.0) tasks :
35
+ register_tasks(/(mssql|sqlserver)/i, MSSQLDatabaseTasks)
36
+ register_tasks(/(oci|oracle)/i, OracleDatabaseTasks)
37
+ # tasks for custom (JDBC) adapters :
38
+ register_tasks(/db2/i, DB2DatabaseTasks)
39
+ register_tasks(/derby/i, DerbyDatabaseTasks)
40
+ register_tasks(/h2/i, H2DatabaseTasks)
41
+ register_tasks(/hsqldb/i, HSQLDBDatabaseTasks)
42
+ # (default) generic JDBC task :
43
+ register_tasks(/^jdbc$/i, JdbcDatabaseTasks)
44
+
45
+ # NOTE: no need to register "built-in" adapters such as MySQL
46
+ # - on 4.0 these are registered and will be instantiated
47
+ # - while on 2.3/3.x we keep the AR built-in task behavior
48
+
49
+ end
50
+ end
@@ -0,0 +1,89 @@
1
+ raise "ArJdbc needs rake 0.9.x or newer" unless Rake.const_defined?(:VERSION)
2
+
3
+ Rake::DSL.module_eval do
4
+
5
+ def redefine_task(*args, &block)
6
+ if Hash === args.first
7
+ task_name = args.first.keys[0]
8
+ old_prereqs = false # leave as specified
9
+ else
10
+ task_name = args.first; old_prereqs = []
11
+ # args[0] = { task_name => old_prereqs }
12
+ end
13
+
14
+ full_name = Rake::Task.scope_name(Rake.application.current_scope, task_name)
15
+
16
+ if old_task = Rake.application.lookup(task_name)
17
+ old_comment = old_task.full_comment
18
+ old_prereqs = old_task.prerequisites.dup if old_prereqs
19
+ old_actions = old_task.actions.dup
20
+ old_actions.shift # remove the main 'action' block - we're redefining it
21
+ # old_task.clear_prerequisites if old_prereqs
22
+ # old_task.clear_actions
23
+ # remove the (old) task instance from the application :
24
+ Rake.application.send(:instance_variable_get, :@tasks)[full_name.to_s] = nil
25
+ else
26
+ # raise "could not find rake task with (full) name '#{full_name}'"
27
+ end
28
+
29
+ new_task = task(*args, &block)
30
+ new_task.comment = old_comment # if old_comment
31
+ new_task.actions.concat(old_actions) if old_actions
32
+ new_task.prerequisites.concat(old_prereqs) if old_prereqs
33
+ new_task
34
+ end
35
+
36
+ end
37
+
38
+ namespace :db do
39
+
40
+ def rails_env
41
+ defined?(Rails.env) ? Rails.env : ( RAILS_ENV || 'development' )
42
+ end
43
+
44
+ def adapt_jdbc_config(config)
45
+ return config unless config['adapter']
46
+ config.merge 'adapter' => config['adapter'].sub(/^jdbc/, '')
47
+ end
48
+
49
+ if defined? ActiveRecord::Tasks::DatabaseTasks # 4.0
50
+
51
+ def current_config(options = {})
52
+ ActiveRecord::Tasks::DatabaseTasks.current_config(options)
53
+ end
54
+
55
+ else # 3.x / 2.3
56
+
57
+ def current_config(options = {}) # not on 2.3
58
+ options = { :env => rails_env }.merge! options
59
+ if options[:config]
60
+ @current_config = options[:config]
61
+ else
62
+ @current_config ||=
63
+ if ENV['DATABASE_URL']
64
+ database_url_config
65
+ else
66
+ ActiveRecord::Base.configurations[options[:env]]
67
+ end
68
+ end
69
+ end
70
+
71
+ def database_url_config(url = ENV['DATABASE_URL'])
72
+ unless defined? ActiveRecord::Base::ConnectionSpecification::Resolver
73
+ raise "ENV['DATABASE_URL'] not support on AR #{ActiveRecord::VERSION::STRING}"
74
+ end
75
+ @database_url_config ||=
76
+ ActiveRecord::Base::ConnectionSpecification::Resolver.new(url, {}).spec.config.stringify_keys
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+ require 'arjdbc/tasks/database_tasks'
84
+
85
+ if defined? ActiveRecord::Tasks::DatabaseTasks # 4.0
86
+ load File.expand_path('databases4.rake', File.dirname(__FILE__))
87
+ else # 3.x / 2.3
88
+ load File.expand_path('databases3.rake', File.dirname(__FILE__))
89
+ end
@@ -0,0 +1,203 @@
1
+ # NOTE: fake these for create_database(config)
2
+ module Mysql
3
+ Error = ActiveRecord::JDBCError unless const_defined?(:Error)
4
+ end
5
+ module Mysql2
6
+ Error = ActiveRecord::JDBCError unless const_defined?(:Error)
7
+ end
8
+
9
+ module ArJdbc
10
+ module Tasks
11
+ class << self
12
+
13
+ # API similar to ActiveRecord::Tasks::DatabaseTasks on AR 4.0
14
+
15
+ def create(config)
16
+ tasks_instance(config).create
17
+ end
18
+
19
+ def drop(config)
20
+ tasks_instance(config).drop
21
+ end
22
+
23
+ def purge(config)
24
+ tasks_instance(config).purge
25
+ end
26
+
27
+ def charset(config)
28
+ tasks_instance(config).charset
29
+ end
30
+
31
+ def collation(config)
32
+ tasks_instance(config).collation
33
+ end
34
+
35
+ def structure_dump(config, filename)
36
+ tasks_instance(config).structure_dump(filename)
37
+ end
38
+
39
+ def structure_load(config, filename)
40
+ tasks_instance(config).structure_load(filename)
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+
47
+ namespace :db do
48
+
49
+ class << self
50
+ alias_method :_rails_create_database, :create_database
51
+ alias_method :_rails_drop_database, :drop_database
52
+ end
53
+
54
+ def create_database(config)
55
+ case config['adapter']
56
+ when /mysql|postgresql|sqlite/
57
+ _rails_create_database adapt_jdbc_config(config)
58
+ else
59
+ ArJdbc::Tasks.create(config)
60
+ end
61
+ end
62
+
63
+ def drop_database(config)
64
+ case config['adapter']
65
+ when /mysql|postgresql|sqlite/
66
+ _rails_drop_database adapt_jdbc_config(config)
67
+ else
68
+ ArJdbc::Tasks.drop(config)
69
+ end
70
+ end
71
+
72
+ redefine_task :charset do # available on 2.3
73
+ ArJdbc::Tasks.charset ActiveRecord::Base.configurations[rails_env]
74
+ end
75
+
76
+ redefine_task :collation do # available on 2.3
77
+ ArJdbc::Tasks.collation ActiveRecord::Base.configurations[rails_env]
78
+ end
79
+
80
+ namespace :structure do
81
+
82
+ redefine_task :dump do
83
+ config = ActiveRecord::Base.configurations[rails_env] # current_config
84
+ filename = structure_sql
85
+
86
+ case config['adapter']
87
+ when /mysql/
88
+ ActiveRecord::Base.establish_connection(config)
89
+ File.open(filename, 'w:utf-8') { |f| f << ActiveRecord::Base.connection.structure_dump }
90
+ when /postgresql/
91
+ ActiveRecord::Base.establish_connection(config)
92
+
93
+ ENV['PGHOST'] = config['host'] if config['host']
94
+ ENV['PGPORT'] = config['port'].to_s if config['port']
95
+ ENV['PGPASSWORD'] = config['password'].to_s if config['password']
96
+ ENV['PGUSER'] = config['username'].to_s if config['username']
97
+
98
+ require 'shellwords'
99
+ search_path = config['schema_search_path']
100
+ unless search_path.blank?
101
+ search_path = search_path.split(",").map{ |part| "--schema=#{Shellwords.escape(part.strip)}" }.join(" ")
102
+ end
103
+ `pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(config['database'])}`
104
+ raise 'Error dumping database' if $?.exitstatus == 1
105
+
106
+ File.open(filename, 'a') { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" }
107
+ when /sqlite/
108
+ dbfile = config['database']
109
+ `sqlite3 #{dbfile} .schema > #{filename}`
110
+ else
111
+ ActiveRecord::Base.establish_connection(config)
112
+ ArJdbc::Tasks.structure_dump(config, filename)
113
+ end
114
+
115
+ if ActiveRecord::Base.connection.supports_migrations?
116
+ File.open(filename, 'a') { |f| f << ActiveRecord::Base.connection.dump_schema_information }
117
+ end
118
+ end
119
+
120
+ redefine_task :load do
121
+ config = ActiveRecord::Base.configurations[rails_env] # current_config
122
+ filename = structure_sql
123
+
124
+ case config['adapter']
125
+ when /mysql/
126
+ ActiveRecord::Base.establish_connection(config)
127
+ ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
128
+ IO.read(filename).split("\n\n").each do |table|
129
+ ActiveRecord::Base.connection.execute(table)
130
+ end
131
+ when /postgresql/
132
+ ENV['PGHOST'] = config['host'] if config['host']
133
+ ENV['PGPORT'] = config['port'].to_s if config['port']
134
+ ENV['PGPASSWORD'] = config['password'].to_s if config['password']
135
+ ENV['PGUSER'] = config['username'].to_s if config['username']
136
+
137
+ `psql -f "#{filename}" #{config['database']}`
138
+ when /sqlite/
139
+ dbfile = config['database']
140
+ `sqlite3 #{dbfile} < "#{filename}"`
141
+ else
142
+ ArJdbc::Tasks.structure_load(config, filename)
143
+ end
144
+ end
145
+
146
+ def structure_sql
147
+ ENV['DB_STRUCTURE'] ||= begin
148
+ root = defined?(Rails.root) ? Rails.root : ( RAILS_ROOT rescue nil )
149
+ if ActiveRecord::VERSION::STRING > '3.2'
150
+ root ? File.join(root, "db", "structure.sql") : File.join("db", "structure.sql")
151
+ else
152
+ root ? File.join(root, "db/#{rails_env}_structure.sql") : "db/#{rails_env}_structure.sql"
153
+ end
154
+ end
155
+ end
156
+
157
+ end
158
+
159
+ namespace :test do
160
+
161
+ # desc "Recreate the test database from an existent structure.sql file"
162
+ redefine_task :load_structure => 'db:test:purge' do # not on 2.3
163
+ begin
164
+ current_config(:config => ActiveRecord::Base.configurations['test'])
165
+ Rake::Task["structure:load"].invoke
166
+ ensure
167
+ current_config(:config => nil)
168
+ end
169
+ end
170
+
171
+ # desc "Recreate the test database from a fresh structure.sql file"
172
+ redefine_task :clone_structure => [ "db:structure:dump", "db:test:load_structure" ]
173
+ # same as on 3.2 - but this task gets changed on 2.3 by depending on :load_structure
174
+
175
+ # desc "Empty the test database"
176
+ redefine_task :purge do
177
+ config = ActiveRecord::Base.configurations['test']
178
+ case config['adapter']
179
+ when /mysql/
180
+ ActiveRecord::Base.establish_connection(:test)
181
+ options = mysql_creation_options(config) rescue config
182
+ ActiveRecord::Base.connection.recreate_database(config['database'], options)
183
+ when /postgresql/
184
+ ActiveRecord::Base.clear_active_connections!
185
+ # drop_database(config) :
186
+ ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
187
+ ActiveRecord::Base.connection.drop_database config['database']
188
+ # create_database(config) :
189
+ encoding = config[:encoding] || ENV['CHARSET'] || 'utf8'
190
+ ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => encoding))
191
+ when /sqlite/
192
+ dbfile = config['database']
193
+ File.delete(dbfile) if File.exist?(dbfile)
194
+ else
195
+ ArJdbc::Tasks.purge(config)
196
+ end
197
+ end
198
+ # only does (:purge => :environment) on AR < 3.2
199
+ task :purge => :load_config if Rake::Task.task_defined?(:load_config)
200
+
201
+ end
202
+
203
+ end