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

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.
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