activerecord-jdbc-alt-adapter 50.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.travis.yml +100 -0
  4. data/.yardopts +4 -0
  5. data/CONTRIBUTING.md +50 -0
  6. data/Gemfile +92 -0
  7. data/History.md +1191 -0
  8. data/LICENSE.txt +26 -0
  9. data/README.md +240 -0
  10. data/RUNNING_TESTS.md +127 -0
  11. data/Rakefile +336 -0
  12. data/Rakefile.jdbc +20 -0
  13. data/activerecord-jdbc-adapter.gemspec +55 -0
  14. data/activerecord-jdbc-alt-adapter.gemspec +56 -0
  15. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  16. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  17. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  18. data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
  19. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  20. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  21. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  22. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  23. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  24. data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
  25. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  26. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  28. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  31. data/lib/activerecord-jdbc-adapter.rb +1 -0
  32. data/lib/arel/visitors/compat.rb +60 -0
  33. data/lib/arel/visitors/db2.rb +137 -0
  34. data/lib/arel/visitors/derby.rb +112 -0
  35. data/lib/arel/visitors/firebird.rb +79 -0
  36. data/lib/arel/visitors/h2.rb +25 -0
  37. data/lib/arel/visitors/hsqldb.rb +32 -0
  38. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  39. data/lib/arel/visitors/sql_server.rb +225 -0
  40. data/lib/arel/visitors/sql_server/ng42.rb +294 -0
  41. data/lib/arel/visitors/sqlserver.rb +214 -0
  42. data/lib/arjdbc.rb +19 -0
  43. data/lib/arjdbc/abstract/connection_management.rb +35 -0
  44. data/lib/arjdbc/abstract/core.rb +74 -0
  45. data/lib/arjdbc/abstract/database_statements.rb +64 -0
  46. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  47. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  48. data/lib/arjdbc/db2.rb +4 -0
  49. data/lib/arjdbc/db2/adapter.rb +789 -0
  50. data/lib/arjdbc/db2/as400.rb +130 -0
  51. data/lib/arjdbc/db2/column.rb +167 -0
  52. data/lib/arjdbc/db2/connection_methods.rb +44 -0
  53. data/lib/arjdbc/derby.rb +3 -0
  54. data/lib/arjdbc/derby/active_record_patch.rb +13 -0
  55. data/lib/arjdbc/derby/adapter.rb +540 -0
  56. data/lib/arjdbc/derby/connection_methods.rb +20 -0
  57. data/lib/arjdbc/derby/schema_creation.rb +15 -0
  58. data/lib/arjdbc/discover.rb +104 -0
  59. data/lib/arjdbc/firebird.rb +4 -0
  60. data/lib/arjdbc/firebird/adapter.rb +434 -0
  61. data/lib/arjdbc/firebird/connection_methods.rb +23 -0
  62. data/lib/arjdbc/h2.rb +3 -0
  63. data/lib/arjdbc/h2/adapter.rb +303 -0
  64. data/lib/arjdbc/h2/connection_methods.rb +27 -0
  65. data/lib/arjdbc/hsqldb.rb +3 -0
  66. data/lib/arjdbc/hsqldb/adapter.rb +297 -0
  67. data/lib/arjdbc/hsqldb/connection_methods.rb +28 -0
  68. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  69. data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
  70. data/lib/arjdbc/informix.rb +5 -0
  71. data/lib/arjdbc/informix/adapter.rb +162 -0
  72. data/lib/arjdbc/informix/connection_methods.rb +9 -0
  73. data/lib/arjdbc/jdbc.rb +59 -0
  74. data/lib/arjdbc/jdbc/adapter.rb +475 -0
  75. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  76. data/lib/arjdbc/jdbc/base_ext.rb +15 -0
  77. data/lib/arjdbc/jdbc/callbacks.rb +53 -0
  78. data/lib/arjdbc/jdbc/column.rb +97 -0
  79. data/lib/arjdbc/jdbc/connection.rb +14 -0
  80. data/lib/arjdbc/jdbc/connection_methods.rb +37 -0
  81. data/lib/arjdbc/jdbc/error.rb +65 -0
  82. data/lib/arjdbc/jdbc/extension.rb +59 -0
  83. data/lib/arjdbc/jdbc/java.rb +13 -0
  84. data/lib/arjdbc/jdbc/railtie.rb +2 -0
  85. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -0
  86. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -0
  87. data/lib/arjdbc/jdbc/type_cast.rb +166 -0
  88. data/lib/arjdbc/jdbc/type_converter.rb +142 -0
  89. data/lib/arjdbc/mssql.rb +7 -0
  90. data/lib/arjdbc/mssql/adapter.rb +384 -0
  91. data/lib/arjdbc/mssql/column.rb +29 -0
  92. data/lib/arjdbc/mssql/connection_methods.rb +79 -0
  93. data/lib/arjdbc/mssql/database_statements.rb +134 -0
  94. data/lib/arjdbc/mssql/errors.rb +6 -0
  95. data/lib/arjdbc/mssql/explain_support.rb +129 -0
  96. data/lib/arjdbc/mssql/extensions.rb +36 -0
  97. data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
  98. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  99. data/lib/arjdbc/mssql/old_adapter.rb +804 -0
  100. data/lib/arjdbc/mssql/old_column.rb +200 -0
  101. data/lib/arjdbc/mssql/quoting.rb +101 -0
  102. data/lib/arjdbc/mssql/schema_creation.rb +31 -0
  103. data/lib/arjdbc/mssql/schema_definitions.rb +74 -0
  104. data/lib/arjdbc/mssql/schema_statements.rb +329 -0
  105. data/lib/arjdbc/mssql/transaction.rb +69 -0
  106. data/lib/arjdbc/mssql/types.rb +52 -0
  107. data/lib/arjdbc/mssql/types/binary_types.rb +33 -0
  108. data/lib/arjdbc/mssql/types/date_and_time_types.rb +134 -0
  109. data/lib/arjdbc/mssql/types/deprecated_types.rb +40 -0
  110. data/lib/arjdbc/mssql/types/numeric_types.rb +71 -0
  111. data/lib/arjdbc/mssql/types/string_types.rb +56 -0
  112. data/lib/arjdbc/mssql/utils.rb +66 -0
  113. data/lib/arjdbc/mysql.rb +3 -0
  114. data/lib/arjdbc/mysql/adapter.rb +140 -0
  115. data/lib/arjdbc/mysql/connection_methods.rb +166 -0
  116. data/lib/arjdbc/oracle/adapter.rb +863 -0
  117. data/lib/arjdbc/postgresql.rb +3 -0
  118. data/lib/arjdbc/postgresql/adapter.rb +687 -0
  119. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  120. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  121. data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
  122. data/lib/arjdbc/postgresql/base/pgconn.rb +11 -0
  123. data/lib/arjdbc/postgresql/column.rb +51 -0
  124. data/lib/arjdbc/postgresql/connection_methods.rb +67 -0
  125. data/lib/arjdbc/postgresql/name.rb +24 -0
  126. data/lib/arjdbc/postgresql/oid_types.rb +266 -0
  127. data/lib/arjdbc/railtie.rb +11 -0
  128. data/lib/arjdbc/sqlite3.rb +3 -0
  129. data/lib/arjdbc/sqlite3/adapter.rb +678 -0
  130. data/lib/arjdbc/sqlite3/connection_methods.rb +59 -0
  131. data/lib/arjdbc/sybase.rb +2 -0
  132. data/lib/arjdbc/sybase/adapter.rb +47 -0
  133. data/lib/arjdbc/tasks.rb +13 -0
  134. data/lib/arjdbc/tasks/database_tasks.rb +31 -0
  135. data/lib/arjdbc/tasks/databases.rake +48 -0
  136. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  137. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  138. data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
  139. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  140. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
  141. data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
  142. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  143. data/lib/arjdbc/util/serialized_attributes.rb +98 -0
  144. data/lib/arjdbc/util/table_copier.rb +110 -0
  145. data/lib/arjdbc/version.rb +3 -0
  146. data/lib/generators/jdbc/USAGE +9 -0
  147. data/lib/generators/jdbc/jdbc_generator.rb +17 -0
  148. data/lib/jdbc_adapter.rb +2 -0
  149. data/lib/jdbc_adapter/rake_tasks.rb +4 -0
  150. data/lib/jdbc_adapter/version.rb +4 -0
  151. data/pom.xml +114 -0
  152. data/rails_generators/jdbc_generator.rb +15 -0
  153. data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
  154. data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
  155. data/rakelib/01-tomcat.rake +51 -0
  156. data/rakelib/02-test.rake +132 -0
  157. data/rakelib/bundler_ext.rb +11 -0
  158. data/rakelib/db.rake +75 -0
  159. data/rakelib/rails.rake +223 -0
  160. data/src/java/arjdbc/ArJdbcModule.java +276 -0
  161. data/src/java/arjdbc/db2/DB2Module.java +76 -0
  162. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +126 -0
  163. data/src/java/arjdbc/derby/DerbyModule.java +178 -0
  164. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +152 -0
  165. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +174 -0
  166. data/src/java/arjdbc/h2/H2Module.java +50 -0
  167. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +85 -0
  168. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +73 -0
  169. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +75 -0
  170. data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
  171. data/src/java/arjdbc/jdbc/Callable.java +44 -0
  172. data/src/java/arjdbc/jdbc/ConnectionFactory.java +45 -0
  173. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
  174. data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
  175. data/src/java/arjdbc/jdbc/DriverWrapper.java +119 -0
  176. data/src/java/arjdbc/jdbc/JdbcResult.java +130 -0
  177. data/src/java/arjdbc/jdbc/RubyConnectionFactory.java +61 -0
  178. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +3979 -0
  179. data/src/java/arjdbc/mssql/MSSQLModule.java +90 -0
  180. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +508 -0
  181. data/src/java/arjdbc/mysql/MySQLModule.java +152 -0
  182. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +294 -0
  183. data/src/java/arjdbc/oracle/OracleModule.java +80 -0
  184. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +455 -0
  185. data/src/java/arjdbc/postgresql/ByteaUtils.java +157 -0
  186. data/src/java/arjdbc/postgresql/PgDateTimeUtils.java +52 -0
  187. data/src/java/arjdbc/postgresql/PostgreSQLModule.java +77 -0
  188. data/src/java/arjdbc/postgresql/PostgreSQLResult.java +192 -0
  189. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +948 -0
  190. data/src/java/arjdbc/sqlite3/SQLite3Module.java +73 -0
  191. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +525 -0
  192. data/src/java/arjdbc/util/CallResultSet.java +826 -0
  193. data/src/java/arjdbc/util/DateTimeUtils.java +699 -0
  194. data/src/java/arjdbc/util/ObjectSupport.java +65 -0
  195. data/src/java/arjdbc/util/QuotingUtils.java +137 -0
  196. data/src/java/arjdbc/util/StringCache.java +63 -0
  197. data/src/java/arjdbc/util/StringHelper.java +145 -0
  198. metadata +269 -0
@@ -0,0 +1,223 @@
1
+ namespace :rails do
2
+
3
+ %w(MySQL SQLite3 PostgreSQL MSSQL).each do |adapter|
4
+
5
+ desc "Run Rails ActiveRecord tests with #{adapter} (JDBC)"
6
+ task "test_#{adapter = adapter.downcase}" do
7
+ puts "Use TESTOPTS=\"--verbose\" to pass --verbose to runners." if ARGV.include? '--verbose'
8
+
9
+ if ENV['RAILS']
10
+ ar_path = File.join(ENV['RAILS'], 'activerecord')
11
+ end
12
+
13
+ unless ar_path && File.exist?(ar_path)
14
+ ar_path = `bundle info --path activerecord`.lines.last.chomp
15
+ end
16
+
17
+ unless File.exist? ar_test_dir = File.join(ar_path, 'test')
18
+ raise "can not directly load Rails tests;" +
19
+ " try setting a local repository path e.g. export RAILS=`pwd`/../rails;" +
20
+ " failed guess: #{ar_path}"
21
+ end
22
+
23
+ driver = "jdbc-#{ENV['DRIVER'] ? ENV['DRIVER'].downcase : (adapter =~ /postgres/i ? 'postgres' : adapter)}"
24
+ adapter = 'mysql2' if adapter.eql?('mysql')
25
+
26
+ # Overriding adapter and driver (maybe we can change later only to mssql)
27
+ if adapter.eql? 'mssql'
28
+ adapter = 'sqlserver'
29
+ ENV['DRIVER'] = 'sqlserver'
30
+ end
31
+
32
+ root_dir = File.expand_path('..', File.dirname(__FILE__))
33
+ env = {}
34
+ env['ARCONFIG'] = ENV['ARCONFIG'] || File.join(root_dir, 'test/rails', 'config.yml')
35
+ env['ARCONN'] = adapter
36
+ env['BUNDLE_GEMFILE'] = ENV['BUNDLE_GEMFILE'] || File.join(root_dir, 'Gemfile') # use AR-JDBC's with Rails tests
37
+ env['EXCLUDE_DIR'] = File.join(root_dir, 'test/rails/excludes', adapter) # minitest-excludes
38
+
39
+ libs = [
40
+ File.join(root_dir, 'lib'),
41
+ File.join(root_dir, driver, 'lib'),
42
+ File.join(root_dir, 'test/rails'),
43
+ ar_test_dir
44
+ ]
45
+
46
+ test_files_finder = lambda do
47
+ Dir.chdir(ar_path) do # taken from Rails' *activerecord/Rakefile* :
48
+ ( Dir.glob("test/cases/**/*_test.rb").reject { |x| x =~ /\/adapters\// } +
49
+ Dir.glob("test/cases/adapters/#{adapter}/**/*_test.rb") )
50
+ end
51
+ end
52
+
53
+ task_stub = Class.new(Rake::TestTask) { def define; end }.new # no-op define
54
+ test_loader_code = task_stub.run_code # :rake test-loader
55
+
56
+ ruby_opts_string = "-I\"#{libs.join(File::PATH_SEPARATOR)}\""
57
+ ruby_opts_string += " -C \"#{ar_path}\""
58
+ ruby_opts_string += " -rbundler/setup"
59
+ ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
60
+ file_list = ENV["TEST"] ? FileList[ ENV["TEST"] ] : test_files_finder.call
61
+ file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
62
+ # test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
63
+ option_list = ( ENV["TESTOPTS"] || ENV["TESTOPT"] || ENV["TEST_OPTS"] || '' )
64
+
65
+ args = "#{ruby_opts_string} #{test_loader_code} #{file_list_string} #{option_list}"
66
+ env_sh env, "#{FileUtils::RUBY} #{args}" do |ok, status|
67
+ if !ok && status.respond_to?(:signaled?) && status.signaled?
68
+ raise SignalException.new(status.termsig)
69
+ elsif !ok
70
+ fail "Command failed with status (#{status.exitstatus})"
71
+ end
72
+ end
73
+ end
74
+ task :test_mysql2 => :test_mysql
75
+
76
+ FileUtils.module_eval do
77
+
78
+ def env_sh(env, *cmd, &block)
79
+ options = (Hash === cmd.last) ? cmd.pop : {}
80
+ shell_runner = block_given? ? block : create_shell_runner(cmd)
81
+ set_verbose_option(options)
82
+ options[:noop] ||= Rake::FileUtilsExt.nowrite_flag
83
+ Rake.rake_check_options options, :noop, :verbose
84
+
85
+ cmd = env.map { |k,v| "#{k}=\"#{v}\"" }.join(' ') + ' ' + cmd.join(' ')
86
+ Rake.rake_output_message cmd if options[:verbose]
87
+
88
+ unless options[:noop]
89
+ res = Kernel.system(cmd)
90
+ status = $?
91
+ status = Rake::PseudoStatus.new(1) if !res && status.nil?
92
+ shell_runner.call(res, status)
93
+ end
94
+ end
95
+
96
+ def env_system(env, cmd)
97
+ Kernel.system(env.map { |k,v| "#{k}=\"#{v}\"" }.join(' ') + ' ' + cmd)
98
+ end
99
+
100
+ end
101
+
102
+ end
103
+
104
+ namespace :db do
105
+ namespace :mysql do
106
+ desc 'Build the MySQL test databases'
107
+ task :build do
108
+ config = ARTest.config['connections']['mysql2']
109
+ %x( mysql --user=#{config['arunit']['username']} --password=#{config['arunit']['password']} -e "create DATABASE #{config['arunit']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
110
+ %x( mysql --user=#{config['arunit2']['username']} --password=#{config['arunit2']['password']} -e "create DATABASE #{config['arunit2']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
111
+ end
112
+
113
+ desc 'Drop the MySQL test databases'
114
+ task :drop do
115
+ config = ARTest.config['connections']['mysql2']
116
+ %x( mysqladmin --user=#{config['arunit']['username']} --password=#{config['arunit']['password']} -f drop #{config['arunit']['database']} )
117
+ %x( mysqladmin --user=#{config['arunit2']['username']} --password=#{config['arunit2']['password']} -f drop #{config['arunit2']['database']} )
118
+ end
119
+
120
+ desc 'Rebuild the MySQL test databases'
121
+ task :rebuild => [:drop, :build]
122
+ end
123
+
124
+ namespace :postgresql do
125
+ desc 'Build the PostgreSQL test databases'
126
+ task :build do
127
+ config = ARTest.config['connections']['postgresql']
128
+ %x( createdb -E UTF8 -T template0 #{config['arunit']['database']} )
129
+ %x( createdb -E UTF8 -T template0 #{config['arunit2']['database']} )
130
+
131
+ # prepare hstore
132
+ if %x( createdb --version ).strip.gsub(/(.*)(\d\.\d\.\d)$/, "\\2") < "9.1.0"
133
+ puts "Please prepare hstore data type. See http://www.postgresql.org/docs/current/static/hstore.html"
134
+ end
135
+ end
136
+
137
+ desc 'Drop the PostgreSQL test databases'
138
+ task :drop do
139
+ config = ARTest.config['connections']['postgresql']
140
+ %x( dropdb #{config['arunit']['database']} )
141
+ %x( dropdb #{config['arunit2']['database']} )
142
+ end
143
+
144
+ desc 'Rebuild the PostgreSQL test databases'
145
+ task :rebuild => [:drop, :build]
146
+ end
147
+ end
148
+
149
+ # NOTE: we expect to, hopefully, not be using these anymore - delete at WILL!
150
+ namespace :test do
151
+ task :all do
152
+ driver = ENV['DRIVER'] || ENV['ADAPTER']
153
+ raise "need a DRIVER (DRIVER=mysql)" unless driver
154
+ rails_dir = _rails_dir
155
+ ENV['ARCONFIG'] = File.join(_ar_jdbc_dir, 'test', 'rails', 'config.yml')
156
+
157
+ Dir.chdir(File.join(rails_dir, 'activerecord')) do
158
+ sh FileUtils::RUBY, '-S', 'rake',
159
+ "RUBYLIB=#{_ruby_lib(rails_dir, driver)}",
160
+ _target(driver)
161
+ end
162
+ end
163
+
164
+ %w(MySQL SQLite3 Postgres).each do |adapter|
165
+ task adapter.downcase do
166
+ ENV['ADAPTER'] = adapter
167
+ Rake::Task['rails:test:all'].invoke
168
+ end
169
+
170
+ namespace adapter.downcase do
171
+ task "base_test" do
172
+ ENV['TEST'] ||= 'test/cases/base_test.rb'
173
+ ENV['ADAPTER'] = adapter
174
+ Rake::Task['rails:test:all'].invoke
175
+ end
176
+ end
177
+ end
178
+
179
+ private
180
+
181
+ def _ar_jdbc_dir
182
+ @ar_jdbc_dir ||= File.expand_path('..', File.dirname(__FILE__))
183
+ end
184
+
185
+ def _rails_dir
186
+ rails_dir = ENV['RAILS'] || File.join('..', 'rails')
187
+ unless File.directory? rails_dir
188
+ raise "can't find RAILS source at '#{rails_dir}' (maybe set ENV['RAILS'])"
189
+ end
190
+ rails_dir = File.join(rails_dir, '..') if rails_dir =~ /activerecord$/
191
+ File.expand_path(rails_dir)
192
+ end
193
+
194
+ def _ruby_lib(rails_dir, driver)
195
+ ar_jdbc_dir = _ar_jdbc_dir
196
+
197
+ if driver =~ /postgres/i
198
+ adapter, driver = 'postgresql', 'postgres'
199
+ else
200
+ adapter, driver = driver.downcase, adapter
201
+ end
202
+
203
+ [File.join(ar_jdbc_dir, 'lib'),
204
+ File.join(ar_jdbc_dir, 'test', 'rails'),
205
+ File.join(ar_jdbc_dir, "jdbc-#{driver}", 'lib'),
206
+ File.join(ar_jdbc_dir, "activerecord-jdbc#{adapter}-adapter", 'lib'),
207
+ File.expand_path('activesupport/lib', rails_dir),
208
+ File.expand_path('activemodel/lib', rails_dir),
209
+ File.expand_path('activerecord/lib', rails_dir)
210
+ ].join(':')
211
+ end
212
+
213
+ def _target(name)
214
+ case name
215
+ when /postgres/i
216
+ 'test_postgresql'
217
+ else
218
+ "test_jdbc#{name.downcase}"
219
+ end
220
+ end
221
+
222
+ end
223
+ end
@@ -0,0 +1,276 @@
1
+ /*
2
+ * The MIT License
3
+ *
4
+ * Copyright 2013-2014 Karol Bucek.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ */
24
+ package arjdbc;
25
+
26
+ import java.lang.reflect.InvocationTargetException;
27
+ import java.util.Collection;
28
+ import java.util.HashMap;
29
+ import java.util.Map;
30
+ import java.util.WeakHashMap;
31
+
32
+ import org.jruby.Ruby;
33
+ import org.jruby.RubyArray;
34
+ import org.jruby.RubyClass;
35
+ import org.jruby.RubyModule;
36
+ import org.jruby.RubyString;
37
+ import org.jruby.anno.JRubyMethod;
38
+ import org.jruby.exceptions.RaiseException;
39
+ import org.jruby.runtime.Block;
40
+ import org.jruby.runtime.ThreadContext;
41
+ import org.jruby.runtime.builtin.IRubyObject;
42
+ import org.jruby.util.ByteList;
43
+
44
+ import arjdbc.jdbc.RubyJdbcConnection;
45
+ import static arjdbc.jdbc.RubyJdbcConnection.getJdbcConnection;
46
+
47
+ /**
48
+ * ::ArJdbc
49
+ *
50
+ * @author kares
51
+ */
52
+ public class ArJdbcModule {
53
+
54
+ public static RubyModule load(final Ruby runtime) {
55
+ final RubyModule arJdbc = runtime.getOrCreateModule("ArJdbc");
56
+ arJdbc.defineAnnotatedMethods( ArJdbcModule.class );
57
+ return arJdbc;
58
+ }
59
+
60
+ public static RubyModule get(final Ruby runtime) {
61
+ return runtime.getModule("ArJdbc");
62
+ }
63
+
64
+ public static void warn(final ThreadContext context, final String message) {
65
+ final Ruby runtime = context.runtime;
66
+ get(runtime).callMethod(context, "warn", runtime.newString(message));
67
+ }
68
+
69
+ /**
70
+ * Load the Java parts for the given adapter spec module, e.g. to load
71
+ * ArJdbc::MySQL's Java part: <code>ArJdbc.load_java_part :MySQL</code>
72
+ *
73
+ * NOTE: this method is not intended to be called twice for a given adapter !
74
+ * @param context
75
+ * @param self
76
+ * @param args ( moduleName, [ connectionClass, moduleClass ] )
77
+ * @return true
78
+ */
79
+ @JRubyMethod(name = "load_java_part", meta = true, required = 1, optional = 2)
80
+ public static IRubyObject load_java_part(final ThreadContext context,
81
+ final IRubyObject self, final IRubyObject[] args) {
82
+ final Ruby runtime = context.getRuntime();
83
+
84
+ String connectionClass = args.length > 1 ? args[1].toString() : null;
85
+ String moduleClass = args.length > 2 ? args[2].toString() : null;
86
+
87
+ final String moduleName = args[0].toString(); // e.g. 'MySQL'
88
+ final String packagePrefix = "arjdbc." + moduleName.toLowerCase() + "."; // arjdbc.mysql
89
+
90
+ // NOTE: due previous (backwards compatible) conventions there are
91
+ // 2 things we load, the adapter spec module's Java implemented methods
92
+ // and a custom JdbcConnection class (both are actually optional) e.g. :
93
+ //
94
+ // MySQLModule.load(RubyModule); // 'arjdbc.mysql' package is assumed
95
+ // MySQLRubyJdbcConnection.createMySQLJdbcConnectionClass(Ruby, RubyClass);
96
+ //
97
+
98
+ if (moduleClass == null) {
99
+ // 'arjdbc.mysql.' + 'MySQL' + 'Module'
100
+ moduleClass = packagePrefix + moduleName + "Module";
101
+ }
102
+
103
+ final Class<?> module;
104
+ try {
105
+ module = Class.forName(moduleClass);
106
+ // new convention MySQLModule.load( Ruby runtime ) :
107
+ try {
108
+ invokeStatic(runtime, module, "load", Ruby.class, runtime);
109
+ }
110
+ catch (NoSuchMethodException e) {
111
+ // old convention MySQLModule.load( RubyModule arJdbc ) :
112
+ invokeStatic(runtime, module, "load", RubyModule.class, get(runtime));
113
+ }
114
+ }
115
+ catch (ClassNotFoundException e) { /* ignored */ }
116
+ catch (NoSuchMethodException e) {
117
+ throw newNativeException(runtime, e);
118
+ }
119
+
120
+ String connectionClass2 = null;
121
+ if (connectionClass == null) {
122
+ // 'arjdbc.mysql.' + 'MySQL' + 'RubyJdbcConnection'
123
+ connectionClass = packagePrefix + moduleName + "RubyJdbcConnection";
124
+ connectionClass2 = packagePrefix + moduleName + "JdbcConnection";
125
+ }
126
+
127
+ try {
128
+ Class<?> connection = null;
129
+ try {
130
+ connection = Class.forName(connectionClass);
131
+ }
132
+ catch (ClassNotFoundException e) {
133
+ if ( connectionClass2 != null ) {
134
+ connection = Class.forName(connectionClass2);
135
+ }
136
+ }
137
+ if ( connection != null ) {
138
+ // convention e.g. MySQLRubyJdbcConnection.load( Ruby runtime ) :
139
+ try {
140
+ invokeStatic(runtime, connection, "load", Ruby.class, runtime);
141
+ }
142
+ catch (NoSuchMethodException e) {
143
+ // "old" e.g. MySQLRubyJdbcConnection.createMySQLJdbcConnectionClass(runtime, jdbcConnection)
144
+ connection.getMethod("create" + moduleName + "JdbcConnectionClass", Ruby.class, RubyClass.class).
145
+ invoke(null, runtime, getJdbcConnection(runtime));
146
+ }
147
+ }
148
+ }
149
+ catch (ClassNotFoundException e) { /* ignored */ }
150
+ catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
151
+ throw newNativeException(runtime, e);
152
+ }
153
+
154
+ return runtime.getTrue();
155
+ }
156
+
157
+ /**
158
+ * <code>ArJdbc.modules</code>
159
+ * @param context
160
+ * @param self
161
+ * @return nested constant values that are modules
162
+ */
163
+ @JRubyMethod(name = "modules", meta = true)
164
+ public static IRubyObject modules(final ThreadContext context, final IRubyObject self) {
165
+ final Ruby runtime = context.getRuntime();
166
+ final RubyModule arJdbc = (RubyModule) self;
167
+
168
+ final Collection<String> constants = arJdbc.getConstantNames();
169
+ final RubyArray modules = runtime.newArray( constants.size() );
170
+
171
+ for ( final String name : constants ) {
172
+ final IRubyObject constant = arJdbc.getConstant(name, false);
173
+ // isModule: return false for Ruby Classes
174
+ if ( constant != null && constant.isModule() ) {
175
+ if ( "Util".equals(name) ) continue;
176
+ if ( "SerializedAttributesHelper".equals(name) ) continue; // deprecated
177
+ if ( "Version".equals(name) ) continue; // deprecated
178
+ modules.append( constant );
179
+ }
180
+ }
181
+ return modules;
182
+ }
183
+
184
+ // JDBC "driver" gem helper(s) :
185
+
186
+ @JRubyMethod(name = "load_driver", meta = true)
187
+ public static IRubyObject load_driver(final ThreadContext context, final IRubyObject self,
188
+ final IRubyObject const_name) { // e.g. load_driver(:MySQL)
189
+ IRubyObject loaded = loadDriver(context, self, const_name.toString());
190
+ return loaded == null ? context.nil : loaded;
191
+ }
192
+
193
+ // NOTE: probably useless - only to be useful for the pooled runtime mode when jar at WEB-INF/lib
194
+ static final Map<Ruby, Map<String, Boolean>> loadedDrivers = new WeakHashMap<Ruby, Map<String, Boolean>>(8);
195
+
196
+ private static IRubyObject loadDriver(final ThreadContext context, final IRubyObject self,
197
+ final String constName) {
198
+ final Ruby runtime = context.runtime;
199
+ // look for "cached" loading result :
200
+ Map<String, Boolean> loadedMap = loadedDrivers.get(runtime);
201
+ if ( loadedMap == null ) {
202
+ synchronized (ArJdbcModule.class) {
203
+ loadedMap = loadedDrivers.get(runtime);
204
+ if ( loadedMap == null ) {
205
+ loadedMap = new HashMap<String, Boolean>(4);
206
+ loadedDrivers.put(runtime, loadedMap);
207
+ }
208
+ }
209
+ }
210
+
211
+ final Boolean driverLoaded = loadedMap.get(constName);
212
+ if ( driverLoaded != null ) {
213
+ if ( driverLoaded.booleanValue() ) return runtime.getFalse();
214
+ return runtime.getNil();
215
+ }
216
+
217
+ try { // require 'jdbc/mysql'
218
+ final byte[] name = new byte[5 + constName.length()]; // 'j','d','b','c','/'
219
+ name[0] = 'j'; name[1] = 'd'; name[2] = 'b'; name[3] = 'c'; name[4] = '/';
220
+ for ( int i = 0; i < constName.length(); i++ ) {
221
+ name[ 5 + i ] = (byte) Character.toLowerCase( constName.charAt(i) );
222
+ }
223
+ final RubyString strName = RubyString.newString(runtime, new ByteList(name, false));
224
+ self.callMethod(context, "require", strName); // require 'jdbc/mysql'
225
+ }
226
+ catch (RaiseException e) { // LoadError
227
+ synchronized (loadedMap) {
228
+ loadedMap.put(constName, Boolean.FALSE);
229
+ }
230
+ return null;
231
+ }
232
+
233
+ final RubyModule jdbc = runtime.getModule("Jdbc");
234
+ if ( jdbc != null ) { // Jdbc::MySQL
235
+ final RubyModule constant = (RubyModule) jdbc.getConstantAt(constName);
236
+ if ( constant != null ) { // ::Jdbc::MySQL.load_driver :
237
+ if ( constant.respondsTo("load_driver") ) {
238
+ IRubyObject result = constant.callMethod("load_driver");
239
+ synchronized (loadedMap) {
240
+ loadedMap.put(constName, Boolean.TRUE);
241
+ }
242
+ return result;
243
+ }
244
+ }
245
+ }
246
+
247
+ synchronized (loadedMap) {
248
+ loadedMap.put(constName, Boolean.FALSE);
249
+ }
250
+ return null;
251
+ }
252
+
253
+ private static Object invokeStatic(final Ruby runtime,
254
+ final Class<?> klass, final String name, final Class<?> argType, final Object arg)
255
+ throws NoSuchMethodException {
256
+ try {
257
+ return klass.getMethod(name, argType).invoke(null, arg);
258
+ }
259
+ catch (IllegalAccessException | InvocationTargetException e) {
260
+ throw newNativeException(runtime, e);
261
+ }
262
+ }
263
+
264
+ private static RaiseException newNativeException(final Ruby runtime, final Throwable cause) {
265
+ final RaiseException error = runtime.newRuntimeError(cause.toString());
266
+ error.initCause(cause);
267
+ return error;
268
+ }
269
+
270
+ @JRubyMethod(meta = true)
271
+ public static IRubyObject with_meta_data_from_data_source_if_any(final ThreadContext context,
272
+ final IRubyObject self, final IRubyObject config, final Block block) {
273
+ return RubyJdbcConnection.with_meta_data_from_data_source_if_any(context, self, config, block);
274
+ }
275
+
276
+ }