ActiveRecord-JDBC 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ == 0.2.4
2
+
3
+ * Release coincides with JRuby 0.9.9 release
4
+ * JRuby 0.9.9 is required
5
+ * MySQL close to 100% working
6
+ * Derby improvements
7
+ * DECIMAL/NUMERIC/FLOAT/REAL bugs fixed with type recognition for Oracle, Postgres, etc.
8
+ * HSQLDB has regressed this release and may not be functioning; we'll get it fixed for the
9
+ next one
10
+
1
11
  == 0.2.3
2
12
 
3
13
  * Release coincides (and compatible) with JRuby 0.9.8 release
data/Manifest.txt CHANGED
@@ -3,10 +3,8 @@ Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
5
  LICENSE
6
- lib/jdbc_adapter.rb
7
6
  lib/active_record/connection_adapters/jdbc_adapter.rb
8
7
  lib/active_record/connection_adapters/jdbc_adapter_spec.rb
9
- lib/active_record/connection_adapters/jndi_adapter.rb
10
8
  lib/jdbc_adapter/jdbc_db2.rb
11
9
  lib/jdbc_adapter/jdbc_derby.rb
12
10
  lib/jdbc_adapter/jdbc_firebird.rb
@@ -16,26 +14,34 @@ lib/jdbc_adapter/jdbc_mssql.rb
16
14
  lib/jdbc_adapter/jdbc_mysql.rb
17
15
  lib/jdbc_adapter/jdbc_oracle.rb
18
16
  lib/jdbc_adapter/jdbc_postgre.rb
19
- test/derby_simple_test.rb
20
- test/h2_simple_test.rb
21
- test/hsqldb_simple_test.rb
22
- test/manualTestDatabase.rb
23
- test/minirunit.rb
24
- test/mysql_simple_test.rb
25
- test/simple.rb
17
+ lib/jdbc_adapter/missing_functionality_helper.rb
18
+ lib/jdbc_adapter.rb
19
+ lib/jdbc_adapter_internal.jar
26
20
  test/activerecord/connection_adapters/type_conversion_test.rb
27
21
  test/activerecord/connections/native_jdbc_mysql/connection.rb
28
22
  test/db/derby.rb
29
23
  test/db/h2.rb
30
24
  test/db/hsqldb.rb
25
+ test/db/jndi_config.rb
31
26
  test/db/logger.rb
32
27
  test/db/mysql.rb
28
+ test/db/postgres.rb
29
+ test/derby_simple_test.rb
30
+ test/h2_simple_test.rb
31
+ test/hsqldb_simple_test.rb
32
+ test/jdbc_common.rb
33
+ test/jndi_test.rb
34
+ test/manualTestDatabase.rb
33
35
  test/minirunit/testConnect.rb
34
36
  test/minirunit/testH2.rb
35
37
  test/minirunit/testHsqldb.rb
36
38
  test/minirunit/testLoadActiveRecord.rb
37
39
  test/minirunit/testMysql.rb
38
40
  test/minirunit/testRawSelect.rb
41
+ test/minirunit.rb
39
42
  test/models/auto_id.rb
40
43
  test/models/data_types.rb
41
44
  test/models/entry.rb
45
+ test/mysql_simple_test.rb
46
+ test/postgres_simple_test.rb
47
+ test/simple.rb
data/Rakefile CHANGED
@@ -3,9 +3,44 @@ require 'rake/testtask'
3
3
 
4
4
  task :default => :test
5
5
 
6
+ def java_classpath_arg # myriad of ways to discover JRuby classpath
7
+ begin
8
+ require 'java' # already running in a JRuby JVM
9
+ jruby_cpath = Java::java.lang.System.getProperty('java.class.path')
10
+ rescue LoadError
11
+ end
12
+ unless jruby_cpath
13
+ jruby_cpath = ENV['JRUBY_PARENT_CLASSPATH'] || ENV['JRUBY_HOME'] &&
14
+ FileList["#{ENV['JRUBY_HOME']}/lib/*.jar"].join(File::PATH_SEPARATOR)
15
+ end
16
+ cpath_arg = jruby_cpath ? "-cp #{jruby_cpath}" : ""
17
+ end
18
+
19
+ desc "Compile the native Java code."
20
+ task :java_compile do
21
+ mkdir_p "pkg/classes"
22
+ sh "javac -target 1.4 -source 1.4 -d pkg/classes #{java_classpath_arg} #{FileList['src/java/**/*.java'].join(' ')}"
23
+ sh "jar cf lib/jdbc_adapter_internal.jar -C pkg/classes/ ."
24
+ end
25
+ file "lib/jdbc_adapter_internal.jar" => :java_compile
26
+
27
+ task :more_clean do
28
+ rm_rf FileList['derby*']
29
+ rm_rf FileList['test.db.*']
30
+ rm_rf "test/reports"
31
+ rm_f FileList['lib/*.jar']
32
+ end
33
+
34
+ task :clean => :more_clean
35
+
36
+ task :filelist do
37
+ puts FileList['pkg/**/*'].inspect
38
+ end
39
+
6
40
  desc "Run AR-JDBC tests"
7
41
  if RUBY_PLATFORM =~ /java/
8
- task :test => [:test_mysql, :test_hsqldb, :test_derby]
42
+ # TODO: add more databases into the standard tests here.
43
+ task :test => [:java_compile, :test_mysql, :test_derby]
9
44
  else
10
45
  task :test => [:test_mysql]
11
46
  end
@@ -26,13 +61,30 @@ Rake::TestTask.new(:test_derby) do |t|
26
61
  t.libs << 'test'
27
62
  end
28
63
 
29
- begin
30
- require 'hoe'
64
+ Rake::TestTask.new(:test_postgresql) do |t|
65
+ t.test_files = FileList['test/postgres_simple_test.rb']
66
+ t.libs << 'test'
67
+ end
31
68
 
69
+ task :test_pgsql => [:test_postgresql]
70
+
71
+ Rake::TestTask.new(:test_jndi) do |t|
72
+ t.test_files = FileList['test/jndi_test.rb']
73
+ t.libs << 'test'
74
+ end
75
+
76
+ begin
32
77
  MANIFEST = FileList["History.txt", "Manifest.txt", "README.txt",
33
- "Rakefile", "LICENSE", "lib/**/*.rb", "test/**/*.rb"]
78
+ "Rakefile", "LICENSE", "lib/**/*.rb", "lib/jdbc_adapter_internal.jar", "test/**/*.rb"]
79
+
80
+ file "Manifest.txt" => :manifest
81
+ task :manifest do
82
+ File.open("Manifest.txt", "w") {|f| MANIFEST.each {|n| f << "#{n}\n"} }
83
+ end
84
+ Rake::Task['manifest'].invoke # Always regen manifest, so Hoe has up-to-date list of files
34
85
 
35
- Hoe.new("ActiveRecord-JDBC", "0.2.3") do |p|
86
+ require 'hoe'
87
+ Hoe.new("ActiveRecord-JDBC", "0.2.4") do |p|
36
88
  p.rubyforge_name = "jruby-extras"
37
89
  p.url = "http://jruby-extras.rubyforge.org/ActiveRecord-JDBC"
38
90
  p.author = "Nick Sieger, Ola Bini and JRuby contributors"
@@ -41,15 +93,7 @@ begin
41
93
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
42
94
  p.description = p.paragraphs_of('README.txt', 0...1).join("\n\n")
43
95
  p.extra_deps.reject!{|d| d.first == "hoe"}
44
- end.spec.files = MANIFEST
45
-
46
- # Automated manifest
47
- task :manifest do
48
- File.open("Manifest.txt", "w") {|f| MANIFEST.each {|n| f << "#{n}\n"} }
49
96
  end
50
-
51
- task :package => :manifest
52
- rescue => e
53
- # Install hoe in order to make a release
54
- # puts e.inspect
97
+ rescue LoadError
98
+ puts "You really need Hoe installed to be able to package this gem"
55
99
  end
@@ -1,11 +1,14 @@
1
1
  require 'active_record/connection_adapters/abstract_adapter'
2
2
  require 'java'
3
3
  require 'active_record/connection_adapters/jdbc_adapter_spec'
4
+ require 'jdbc_adapter_internal'
5
+ require 'bigdecimal'
4
6
 
5
7
  module ActiveRecord
6
8
  class Base
7
9
  def self.jdbc_connection(config)
8
- ConnectionAdapters::JdbcAdapter.new(ConnectionAdapters::JdbcConnection.new(config), logger, config)
10
+ connection = ConnectionAdapters::JdbcConnection.new(config)
11
+ ConnectionAdapters::JdbcAdapter.new(connection, logger, config)
9
12
  end
10
13
 
11
14
  alias :attributes_with_quotes_pre_oracle :attributes_with_quotes
@@ -66,41 +69,46 @@ module ActiveRecord
66
69
  # type left. If all the selectors are applied and there is still more than one
67
70
  # type, an exception will be raised.
68
71
  AR_TO_JDBC_TYPES = {
69
- :string => [ lambda {|r| Jdbc::Types::VARCHAR == r['data_type']},
72
+ :string => [ lambda {|r| Jdbc::Types::VARCHAR == r['data_type'].to_i},
70
73
  lambda {|r| r['type_name'] =~ /^varchar/i},
71
74
  lambda {|r| r['type_name'] =~ /^varchar$/i},
72
75
  lambda {|r| r['type_name'] =~ /varying/i}],
73
- :text => [ lambda {|r| [Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB].include?(r['data_type'])},
76
+ :text => [ lambda {|r| [Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB].include?(r['data_type'].to_i)},
74
77
  lambda {|r| r['type_name'] =~ /^(text|clob)/i},
75
78
  lambda {|r| r['type_name'] =~ /^character large object$/i},
76
79
  lambda {|r| r['sql_data_type'] == 2005}],
77
- :integer => [ lambda {|r| Jdbc::Types::INTEGER == r['data_type']},
80
+ :integer => [ lambda {|r| Jdbc::Types::INTEGER == r['data_type'].to_i},
78
81
  lambda {|r| r['type_name'] =~ /^integer$/i},
79
82
  lambda {|r| r['type_name'] =~ /^int4$/i},
80
83
  lambda {|r| r['type_name'] =~ /^int$/i}],
81
- :decimal => [ lambda {|r| Jdbc::Types::DECIMAL == r['data_type']},
82
- lambda {|r| r['type_name'] =~ /^decimal$/i}],
83
- :float => [ lambda {|r| [Jdbc::Types::FLOAT,Jdbc::Types::DOUBLE].include?(r['data_type'])},
84
+ :decimal => [ lambda {|r| Jdbc::Types::DECIMAL == r['data_type'].to_i},
85
+ lambda {|r| r['type_name'] =~ /^decimal$/i},
86
+ lambda {|r| r['type_name'] =~ /^numeric$/i},
87
+ lambda {|r| r['type_name'] =~ /^number$/i},
88
+ lambda {|r| r['precision'] == '38'},
89
+ lambda {|r| r['data_type'] == '2'}],
90
+ :float => [ lambda {|r| [Jdbc::Types::FLOAT,Jdbc::Types::DOUBLE, Jdbc::Types::REAL].include?(r['data_type'].to_i)},
84
91
  lambda {|r| r['type_name'] =~ /^float/i},
85
92
  lambda {|r| r['type_name'] =~ /^double$/i},
86
- lambda {|r| r['precision'] == 15}],
87
- :datetime => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type']},
93
+ lambda {|r| r['type_name'] =~ /^real$/i},
94
+ lambda {|r| r['precision'] == '15'}],
95
+ :datetime => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
88
96
  lambda {|r| r['type_name'] =~ /^datetime/i},
89
97
  lambda {|r| r['type_name'] =~ /^timestamp$/i}],
90
- :timestamp => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type']},
98
+ :timestamp => [ lambda {|r| Jdbc::Types::TIMESTAMP == r['data_type'].to_i},
91
99
  lambda {|r| r['type_name'] =~ /^timestamp$/i},
92
100
  lambda {|r| r['type_name'] =~ /^datetime/i} ],
93
- :time => [ lambda {|r| Jdbc::Types::TIME == r['data_type']},
101
+ :time => [ lambda {|r| Jdbc::Types::TIME == r['data_type'].to_i},
94
102
  lambda {|r| r['type_name'] =~ /^time$/i},
95
103
  lambda {|r| r['type_name'] =~ /^datetime$/i}],
96
- :date => [ lambda {|r| Jdbc::Types::DATE == r['data_type']},
104
+ :date => [ lambda {|r| Jdbc::Types::DATE == r['data_type'].to_i},
97
105
  lambda {|r| r['type_name'] =~ /^date$/i}],
98
- :binary => [ lambda {|r| [Jdbc::Types::LONGVARBINARY,Jdbc::Types::BINARY,Jdbc::Types::BLOB].include?(r['data_type'])},
106
+ :binary => [ lambda {|r| [Jdbc::Types::LONGVARBINARY,Jdbc::Types::BINARY,Jdbc::Types::BLOB].include?(r['data_type'].to_i)},
99
107
  lambda {|r| r['type_name'] =~ /^blob/i},
100
108
  lambda {|r| r['type_name'] =~ /sub_type 0$/i}, # For FireBird
101
109
  lambda {|r| r['type_name'] =~ /^varbinary$/i}, # We want this sucker for Mimer
102
110
  lambda {|r| r['type_name'] =~ /^binary$/i}, ],
103
- :boolean => [ lambda {|r| [Jdbc::Types::TINYINT].include?(r['data_type'])},
111
+ :boolean => [ lambda {|r| [Jdbc::Types::TINYINT].include?(r['data_type'].to_i)},
104
112
  lambda {|r| r['type_name'] =~ /^bool/i},
105
113
  lambda {|r| r['type_name'] =~ /^tinyint$/i},
106
114
  lambda {|r| r['type_name'] =~ /^decimal$/i}],
@@ -114,8 +122,8 @@ module ActiveRecord
114
122
  type_map = {}
115
123
  AR_TO_JDBC_TYPES.each_key do |k|
116
124
  typerow = choose_type(k)
117
- type_map[k] = { :name => typerow['type_name'] }
118
- type_map[k][:limit] = typerow['precision'] if [:integer, :string, :decimal].include?(k)
125
+ type_map[k] = { :name => typerow['type_name'].downcase }
126
+ type_map[k][:limit] = typerow['precision'] && typerow['precision'].to_i if [:integer, :string, :decimal].include?(k)
119
127
  type_map[k][:limit] = 1 if k == :boolean
120
128
  end
121
129
  type_map
@@ -129,7 +137,7 @@ module ActiveRecord
129
137
  return new_types.first if new_types.length == 1
130
138
  types = new_types if new_types.length > 0
131
139
  end
132
- raise "unable to choose type from: #{types.collect{|t| [t['type_name'],t]}.inspect} for #{ar_type}"
140
+ raise "unable to choose type from: #{types.collect{|t| [t['type_name'],t]}.inspect} for #{ar_type}"
133
141
  end
134
142
  end
135
143
 
@@ -146,8 +154,11 @@ module ActiveRecord
146
154
  end
147
155
 
148
156
  class JdbcColumn < Column
157
+ attr_writer :limit, :precision
158
+
149
159
  COLUMN_TYPES = {
150
160
  /oracle/i => lambda {|cfg,col| col.extend(JdbcSpec::Oracle::Column)},
161
+ /mysql/i => lambda {|cfg,col| col.extend(JdbcSpec::MySQL::Column)},
151
162
  /postgre/i => lambda {|cfg,col| col.extend(JdbcSpec::PostgreSQL::Column)},
152
163
  /sqlserver|tds/i => lambda {|cfg,col| col.extend(JdbcSpec::MsSQL::Column)},
153
164
  /hsqldb|\.h2\./i => lambda {|cfg,col| col.extend(JdbcSpec::HSQLDB::Column)},
@@ -168,6 +179,10 @@ module ActiveRecord
168
179
  end
169
180
  end
170
181
  super(name,default_value(default),*args)
182
+ init_column(name, default, *args)
183
+ end
184
+
185
+ def init_column(*args)
171
186
  end
172
187
 
173
188
  def default_value(val)
@@ -176,95 +191,26 @@ module ActiveRecord
176
191
  end
177
192
 
178
193
  class JdbcConnection
194
+ attr_reader :adapter
195
+
179
196
  def initialize(config)
180
- @config = config.symbolize_keys
181
- driver = @config[:driver].to_s
182
- user = @config[:username].to_s
183
- pass = @config[:password].to_s
184
- url = @config[:url].to_s
185
-
186
- unless driver && url
187
- raise ArgumentError, "jdbc adapter requires driver class and url"
197
+ @config = config.symbolize_keys!
198
+ if @config[:jndi]
199
+ configure_jndi
200
+ else
201
+ configure_jdbc
188
202
  end
189
-
190
- JdbcDriver.load(driver)
191
- @connection = Jdbc::DriverManager.getConnection(url, user, pass)
192
203
  set_native_database_types
193
-
194
204
  @stmts = {}
195
205
  rescue Exception => e
196
- raise "The driver encounter an error: #{e}"
197
- end
198
-
199
- def ps(sql)
200
- @connection.prepareStatement(sql)
201
- end
202
-
203
- def set_native_database_types
204
- types = unmarshal_result(@connection.getMetaData.getTypeInfo)
205
- @native_types = JdbcTypeConverter.new(types).choose_best_types
206
- end
207
-
208
- def native_database_types(adapt)
209
- types = {}
210
- @native_types.each_pair {|k,v| types[k] = v.inject({}) {|memo,kv| memo.merge({kv.first => (kv.last.dup rescue kv.last)})}}
211
- adapt.modify_types(types)
206
+ raise "The driver encountered an error: #{e}"
212
207
  end
213
-
214
- def columns(table_name, name = nil)
215
- metadata = @connection.getMetaData
216
- table_name.upcase! if metadata.storesUpperCaseIdentifiers
217
- table_name.downcase! if metadata.storesLowerCaseIdentifiers
218
- results = metadata.getColumns(nil, nil, table_name, nil)
219
- columns = []
220
- unmarshal_result(results).each do |col|
221
- column_name = col['column_name']
222
- column_name = column_name.downcase if metadata.storesUpperCaseIdentifiers
223
- precision = col["column_size"]
224
- scale = col["decimal_digits"]
225
- coltype = col["type_name"]
226
- if precision && precision > 0
227
- coltype << "(#{precision}"
228
- coltype << ",#{scale}" if scale && scale > 0
229
- coltype << ")"
230
- end
231
- columns << ActiveRecord::ConnectionAdapters::JdbcColumn.new(@config, column_name, col['column_def'],
232
- coltype, col['is_nullable'] != 'NO')
233
- end
234
- columns
235
- rescue
236
- if @connection.is_closed
237
- reconnect!
238
- retry
239
- else
240
- raise
241
- end
242
- end
243
-
244
- def tables(&table_filter)
245
- metadata = @connection.getMetaData
246
- results = metadata.getTables(nil, nil, nil, nil)
247
- unmarshal_result(results, &table_filter).collect {|t| t['table_name'].downcase }
248
- rescue
249
- if @connection.is_closed
250
- reconnect!
251
- retry
252
- else
253
- raise
254
- end
255
- end
256
-
257
- # Get a list of all primary keys associated with the given table
258
- def primary_keys(table_name)
259
- meta_data = @connection.getMetaData
260
- result_set = meta_data.get_primary_keys(nil, nil, table_name.to_s.upcase)
261
- key_names = []
262
-
263
- while result_set.next
264
- key_names << result_set.get_string(Jdbc::PrimaryKeyMetaData::COLUMN_NAME).downcase
265
- end
266
-
267
- key_names
208
+
209
+ def adapter=(adapt)
210
+ @adapter = adapt
211
+ @tps = {}
212
+ @native_types.each_pair {|k,v| @tps[k] = v.inject({}) {|memo,kv| memo.merge({kv.first => (kv.last.dup rescue kv.last)})}}
213
+ adapt.modify_types(@tps)
268
214
  end
269
215
 
270
216
  # Default JDBC introspection for index metadata on the JdbcConnection.
@@ -277,7 +223,14 @@ module ActiveRecord
277
223
  # should filter the return from this method instead.
278
224
  def indexes(table_name, name = nil)
279
225
  metadata = @connection.getMetaData
280
- resultset = metadata.getIndexInfo(nil, nil, table_name.to_s.upcase, false, false)
226
+ unless String === table_name
227
+ table_name = table_name.to_s
228
+ else
229
+ table_name = table_name.dup
230
+ end
231
+ table_name.upcase! if metadata.storesUpperCaseIdentifiers
232
+ table_name.downcase! if metadata.storesLowerCaseIdentifiers
233
+ resultset = metadata.getIndexInfo(nil, nil, table_name, false, false)
281
234
  primary_keys = primary_keys(table_name)
282
235
  indexes = []
283
236
  current_index = nil
@@ -311,180 +264,37 @@ module ActiveRecord
311
264
  end
312
265
  end
313
266
 
314
-
315
- def execute_insert(sql, pk)
316
- stmt = @connection.createStatement
317
- stmt.executeUpdate(sql,Jdbc::Statement::RETURN_GENERATED_KEYS)
318
- row = unmarshal_id_result(stmt.getGeneratedKeys)
319
- row.first && row.first.values.first
320
- rescue
321
- if @connection.is_closed
322
- reconnect!
323
- retry
324
- else
325
- raise
326
- end
327
- ensure
328
- stmt.close
329
- end
330
-
331
- def execute_update(sql)
332
- stmt = @connection.createStatement
333
- stmt.executeUpdate(sql)
334
- rescue
335
- if @connection.is_closed
336
- reconnect!
337
- retry
338
- else
339
- raise
340
- end
341
- ensure
342
- stmt.close
343
- end
344
-
345
- def execute_query(sql)
346
- stmt = @connection.createStatement
347
- unmarshal_result(stmt.executeQuery(sql))
348
- rescue
349
- if @connection.is_closed
350
- reconnect!
351
- retry
352
- else
353
- raise
354
- end
355
- ensure
356
- stmt.close
357
- end
358
-
359
- def begin
360
- @connection.setAutoCommit(false)
361
- end
362
-
363
- def commit
364
- @connection.commit
365
- ensure
366
- @connection.setAutoCommit(true)
367
- end
368
-
369
- def rollback
370
- @connection.rollback
371
- ensure
372
- @connection.setAutoCommit(true)
373
- end
374
-
375
267
  private
376
- def unmarshal_result(resultset, &row_filter)
377
- metadata = resultset.getMetaData
378
- column_count = metadata.getColumnCount
379
- column_names = ['']
380
- column_types = ['']
381
- column_scale = ['']
382
-
383
- 1.upto(column_count) do |i|
384
- column_names << metadata.getColumnName(i)
385
- column_types << metadata.getColumnType(i)
386
- column_scale << metadata.getScale(i)
268
+ def configure_jndi
269
+ jndi = @config[:jndi].to_s
270
+ ctx = javax.naming.InitialContext.new
271
+ ds = ctx.lookup(jndi)
272
+ set_connection ds.connection
273
+ unless @config[:driver]
274
+ @config[:driver] = @connection.meta_data.connection.java_class.name
387
275
  end
388
-
389
- results = []
390
-
391
- # take all rows if block not supplied
392
- row_filter = lambda{|result_row| true} unless block_given?
393
-
394
- while resultset.next
395
- # let the supplied block look at this row from the resultset to
396
- # see if we want to include it in our results
397
- if row_filter.call(resultset)
398
- row = {}
399
- 1.upto(column_count) do |i|
400
- row[column_names[i].downcase] = convert_jdbc_type_to_ruby(i, column_types[i], column_scale[i], resultset)
401
- end
402
- results << row
403
- end
404
- end
405
-
406
- results
407
276
  end
408
277
 
409
- def unmarshal_id_result(resultset)
410
- metadata = resultset.getMetaData
411
- column_count = metadata.getColumnCount
412
- column_types = ['']
413
- column_scale = ['']
414
-
415
- 1.upto(column_count) do |i|
416
- column_types << metadata.getColumnType(i)
417
- column_scale << metadata.getScale(i)
418
- end
419
-
420
- results = []
278
+ def configure_jdbc
279
+ driver = @config[:driver].to_s
280
+ user = @config[:username].to_s
281
+ pass = @config[:password].to_s
282
+ url = @config[:url].to_s
421
283
 
422
- while resultset.next
423
- row = {}
424
- 1.upto(column_count) do |i|
425
- row[i] = row[i.to_s] = convert_jdbc_type_to_ruby(i, column_types[i], column_scale[i], resultset)
426
- end
427
- results << row
284
+ unless driver && url
285
+ raise ArgumentError, "jdbc adapter requires driver class and url"
428
286
  end
429
-
430
- results
431
- end
432
-
433
- def to_ruby_time(java_time)
434
- if java_time
435
- tm = java_time.getTime
436
- Time.at(tm / 1000, (tm % 1000) * 1000)
287
+
288
+ if driver =~ /mysql/i
289
+ div = url =~ /\?/ ? '&' : '?'
290
+ url = "#{url}#{div}zeroDateTimeBehavior=convertToNull&jdbcCompliantTruncation=false"
291
+ @config[:url] = url
437
292
  end
438
- end
439
293
 
440
- def to_ruby_date(java_date)
441
- if java_date
442
- cal = java.util.Calendar.getInstance
443
- cal.setTime(java_date)
444
- Date.new(cal.get(java.util.Calendar::YEAR), cal.get(java.util.Calendar::MONTH)+1, cal.get(java.util.Calendar::DATE))
445
- end
294
+ JdbcDriver.load(driver)
295
+ set_connection Jdbc::DriverManager.getConnection(url, user, pass)
446
296
  end
447
297
 
448
- def convert_jdbc_type_to_ruby(row, type, scale, resultset)
449
- value = case type
450
- when Jdbc::Types::CHAR, Jdbc::Types::VARCHAR, Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB
451
- resultset.getString(row)
452
- when Jdbc::Types::NUMERIC, Jdbc::Types::BIGINT
453
- if scale != 0
454
- BigDecimal.new(resultset.getBigDecimal(row).toString)
455
- else
456
- resultset.getLong(row)
457
- end
458
- when Jdbc::Types::DECIMAL
459
- BigDecimal.new(resultset.getBigDecimal(row).toString)
460
- when Jdbc::Types::SMALLINT, Jdbc::Types::INTEGER
461
- resultset.getInt(row)
462
- when Jdbc::Types::BIT, Jdbc::Types::BOOLEAN, Jdbc::Types::TINYINT
463
- resultset.getBoolean(row)
464
- when Jdbc::Types::FLOAT, Jdbc::Types::DOUBLE
465
- resultset.getDouble(row)
466
- when Jdbc::Types::TIMESTAMP
467
- # FIXME: This should not be a catchall and it should move this to mysql since it
468
- # is catching non-existent date 0000-00:00:00
469
- begin
470
- to_ruby_time(resultset.getTimestamp(row))
471
- rescue java.sql.SQLException
472
- nil
473
- end
474
- when Jdbc::Types::TIME
475
- to_ruby_time(resultset.getTime(row))
476
- when Jdbc::Types::DATE
477
- to_ruby_date(resultset.getDate(row))
478
- when Jdbc::Types::LONGVARBINARY, Jdbc::Types::BLOB, Jdbc::Types::BINARY, Jdbc::Types::VARBINARY
479
- resultset.getString(row)
480
- else
481
- raise "jdbc_adapter: type #{jdbc_type_name(type)} not supported yet"
482
- end
483
- resultset.wasNull ? nil : value
484
- end
485
- def jdbc_type_name(type)
486
- Jdbc::Types.constants.find {|t| Jdbc::Types.const_get(t.to_sym) == type}
487
- end
488
298
  end
489
299
 
490
300
  class JdbcAdapter < AbstractAdapter
@@ -515,6 +325,7 @@ module ActiveRecord
515
325
  func.call(@config,self)
516
326
  end
517
327
  end
328
+ connection.adapter = self
518
329
  end
519
330
 
520
331
  def modify_types(tp)
@@ -529,10 +340,14 @@ module ActiveRecord
529
340
  true
530
341
  end
531
342
 
532
- def native_database_types #:nodoc
533
- @connection.native_database_types(self)
343
+ def native_database_types #:nodoc:
344
+ @connection.native_database_types
534
345
  end
535
346
 
347
+ def database_name #:nodoc:
348
+ @connection.database_name
349
+ end
350
+
536
351
  def native_sql_to_type(tp)
537
352
  if /^(.*?)\(([0-9]+)\)/ =~ tp
538
353
  tname = $1
@@ -568,13 +383,9 @@ module ActiveRecord
568
383
  return nil,nil
569
384
  end
570
385
 
571
- def active?
572
- true
573
- end
574
-
575
386
  def reconnect!
576
387
  @connection.close rescue nil
577
- @connection = JdbcConnection.new(@config,self)
388
+ @connection = JdbcConnection.new(@config)
578
389
  end
579
390
 
580
391
  def select_all(sql, name = nil)
@@ -587,22 +398,24 @@ module ActiveRecord
587
398
 
588
399
  def execute(sql, name = nil)
589
400
  log_no_bench(sql, name) do
590
- if sql =~ /^(select|show)/i
591
- @connection.execute_query(sql)
401
+ case sql.strip
402
+ when /^(select|show)/i:
403
+ @connection.execute_query(sql)
404
+ when /^insert/i:
405
+ @connection.execute_insert(sql)
592
406
  else
593
407
  @connection.execute_update(sql)
594
408
  end
595
409
  end
596
410
  end
597
411
 
598
- alias :update :execute
599
- alias :delete :execute
412
+ def update(sql, name = nil) #:nodoc:
413
+ execute(sql, name)
414
+ end
600
415
 
601
416
  def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
602
- log_no_bench(sql, name) do
603
- id = @connection.execute_insert(sql, pk)
604
- id_value || id
605
- end
417
+ id = execute(sql, name = nil)
418
+ id_value || id
606
419
  end
607
420
 
608
421
  def columns(table_name, name = nil)
@@ -627,7 +440,7 @@ module ActiveRecord
627
440
 
628
441
  private
629
442
  def select(sql, name=nil)
630
- log_no_bench(sql, name) { @connection.execute_query(sql) }
443
+ execute(sql,name)
631
444
  end
632
445
 
633
446
  def log_no_bench(sql, name)