ActiveRecord-JDBC 0.0.1

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 Nick Sieger <nick@nicksieger.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/init.rb ADDED
@@ -0,0 +1,8 @@
1
+ RAILS_CONNECTION_ADAPTERS << 'jdbc'
2
+ require 'active_record/connection_adapters/jdbc_adapter'
3
+
4
+ [:initialize_database, :initialize_framework_logging, :initialize_framework_settings].each do |cmd|
5
+ Rails::Initializer.run(cmd) do |config|
6
+ config.frameworks = [:active_record]
7
+ end
8
+ end
@@ -0,0 +1,25 @@
1
+
2
+ require 'fileutils'
3
+
4
+ from_d=File.expand_path(File.join(File.dirname(__FILE__),'lib','active_record'))
5
+ to_d=File.expand_path(File.join(RAILS_ROOT,'lib','active_record'))
6
+
7
+ FileUtils.cp_r from_d, to_d
8
+
9
+ env_file = File.expand_path(File.join(RAILS_ROOT,"config","environment.rb"))
10
+ bck_file = File.expand_path(File.join(RAILS_ROOT,"config","~.environment.rb.before_jdbc"))
11
+
12
+ FileUtils.mv env_file,bck_file
13
+
14
+ File.open(bck_file,"r") {|inf|
15
+ File.open(env_file,"w") {|out|
16
+ inf.each_line do |ln|
17
+ if ln =~ /^Rails::Initializer\.run/
18
+ out.puts "# Added by ActiveRecord JDBC plugin"
19
+ out.puts "RAILS_CONNECTION_ADAPTERS = %w( jdbc mysql postgresql sqlite firebird sqlserver db2 oracle sybase openbase )"
20
+ out.puts
21
+ end
22
+ out.puts ln
23
+ end
24
+ }
25
+ }
@@ -0,0 +1,358 @@
1
+ require 'active_record/connection_adapters/abstract_adapter'
2
+
3
+ module ActiveRecord
4
+ class Base
5
+ def self.jdbc_connection(config)
6
+ ConnectionAdapters::JdbcAdapter.new(ConnectionAdapters::JdbcConnection.new(config), logger, config)
7
+ end
8
+ end
9
+
10
+ module ConnectionAdapters
11
+ module Jdbc
12
+ require 'java'
13
+ include_class 'java.sql.DriverManager'
14
+ include_class 'java.sql.Statement'
15
+ include_class 'java.sql.Types'
16
+ end
17
+
18
+ # I want to use JDBC's DatabaseMetaData#getTypeInfo to choose the best native types to
19
+ # use for ActiveRecord's Adapter#native_database_types in a database-independent way,
20
+ # but apparently a database driver can return multiple types for a given
21
+ # java.sql.Types constant. So this type converter uses some heuristics to try to pick
22
+ # the best (most common) type to use. It's not great, it would be better to just
23
+ # delegate to each database's existin AR adapter's native_database_types method, but I
24
+ # wanted to try to do this in a way that didn't pull in all the other adapters as
25
+ # dependencies. Suggestions appreciated.
26
+ class JdbcTypeConverter
27
+ # The basic ActiveRecord types, mapped to an array of procs that are used to #select
28
+ # the best type. The procs are used as selectors in order until there is only one
29
+ # type left. If all the selectors are applied and there is still more than one
30
+ # type, an exception will be raised.
31
+ AR_TO_JDBC_TYPES = {
32
+ :string => [ proc {|r| Jdbc::Types::VARCHAR == r['data_type']},
33
+ proc {|r| r['type_name'] =~ /^varchar/i} ],
34
+ :text => [ proc {|r| [Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB].include?(r['data_type'])},
35
+ proc {|r| r['type_name'] =~ /^(text|clob)/i} ],
36
+ :integer => [ proc {|r| Jdbc::Types::INTEGER == r['data_type']},
37
+ proc {|r| r['type_name'] =~ /^integer/i} ],
38
+ :float => [ proc {|r| [Jdbc::Types::FLOAT,Jdbc::Types::DOUBLE].include?(r['data_type'])},
39
+ proc {|r| r['type_name'] =~ /^float/i},
40
+ proc {|r| r['type_name'] =~ /^double$/i} ],
41
+ :datetime => [ proc {|r| Jdbc::Types::TIMESTAMP == r['data_type']},
42
+ proc {|r| r['type_name'] =~ /^datetime/i} ],
43
+ :timestamp => [ proc {|r| Jdbc::Types::TIMESTAMP == r['data_type']},
44
+ proc {|r| r['type_name'] =~ /^timestamp/i},
45
+ proc {|r| r['type_name'] =~ /^datetime/i} ],
46
+ :time => [ proc {|r| Jdbc::Types::TIME == r['data_type']} ],
47
+ :date => [ proc {|r| Jdbc::Types::DATE == r['data_type']} ],
48
+ :binary => [ proc {|r| Jdbc::Types::LONGVARBINARY == r['data_type']},
49
+ proc {|r| r['type_name'] =~ /^blob/i} ],
50
+ :boolean => [ proc {|r| Jdbc::Types::TINYINT == r['data_type']} ]
51
+ }
52
+
53
+ def initialize(types)
54
+ @types = types
55
+ end
56
+
57
+ def choose_best_types
58
+ type_map = {}
59
+ AR_TO_JDBC_TYPES.each_key do |k|
60
+ typerow = choose_type(k)
61
+ type_map[k] = { :name => typerow['type_name'] }
62
+ type_map[k][:limit] = typerow['precision'] if [:integer,:string].include?(k)
63
+ type_map[k][:limit] = 1 if k == :boolean
64
+ end
65
+ type_map
66
+ end
67
+
68
+ def choose_type(ar_type)
69
+ procs = AR_TO_JDBC_TYPES[ar_type]
70
+ types = @types
71
+ procs.each do |p|
72
+ new_types = types.select(&p)
73
+ return new_types.first if new_types.length == 1
74
+ types = new_types if new_types.length > 0
75
+ end
76
+ raise "unable to choose type from: #{types.collect{|t| t['type_name']}.inspect}"
77
+ end
78
+ end
79
+
80
+ class JdbcDriver
81
+ def self.load(driver)
82
+ driver_class_const = (driver[0...1].capitalize + driver[1..driver.length]).gsub(/\./, '_')
83
+ unless Jdbc.const_defined?(driver_class_const)
84
+ Jdbc.module_eval do
85
+ include_class(driver) {|p,c| driver_class_const }
86
+ end
87
+ driver_class = Jdbc.const_get(driver_class_const.to_sym)
88
+ Jdbc::DriverManager.registerDriver(driver_class.new)
89
+ end
90
+ end
91
+ end
92
+
93
+ class JdbcConnection
94
+ def initialize(config)
95
+ config = config.symbolize_keys
96
+ driver = config[:driver].to_s
97
+ user = config[:username].to_s
98
+ pass = config[:password].to_s
99
+ url = config[:url].to_s
100
+
101
+ unless driver && url
102
+ raise ArgumentError, "jdbc adapter requires driver class and url"
103
+ end
104
+
105
+ JdbcDriver.load(driver)
106
+ @connection = Jdbc::DriverManager.getConnection(url, user, pass)
107
+ set_native_database_types
108
+ end
109
+
110
+ def set_native_database_types
111
+ types = unmarshal_result(@connection.getMetaData.getTypeInfo)
112
+ @native_types = JdbcTypeConverter.new(types).choose_best_types
113
+ end
114
+
115
+ def native_database_types
116
+ types = {
117
+ # TODO: this is copied from MySQL -- figure out how to
118
+ # generalize the primary key type
119
+ :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY",
120
+ }
121
+ @native_types.each_pair {|k,v| types[k] = v.inject({}) {|memo,kv| memo.merge({kv.first => kv.last.dup})}}
122
+ types
123
+ end
124
+
125
+ def columns(table_name, name = nil)
126
+ metadata = @connection.getMetaData
127
+ results = metadata.getColumns(nil, nil, table_name, nil)
128
+ columns = []
129
+ unmarshal_result(results).each do |col|
130
+ columns << ActiveRecord::ConnectionAdapters::Column.new(col['column_name'], col['column_def'],
131
+ "#{col['type_name']}(#{col['column_size']})", col['is_nullable'] != 'NO')
132
+ end
133
+ columns
134
+ end
135
+
136
+ def tables
137
+ metadata = @connection.getMetaData
138
+ results = metadata.getTables(nil, nil, nil, nil)
139
+ unmarshal_result(results).collect {|t| t['table_name']}
140
+ end
141
+
142
+ def execute_insert(sql, pk)
143
+ stmt = @connection.createStatement
144
+ stmt.executeUpdate(sql, Jdbc::Statement::RETURN_GENERATED_KEYS)
145
+ row = unmarshal_result(stmt.getGeneratedKeys)
146
+ row.first && row.first.values.first
147
+ ensure
148
+ stmt.close
149
+ end
150
+
151
+ def execute_update(sql)
152
+ stmt = @connection.createStatement
153
+ stmt.executeUpdate(sql)
154
+ ensure
155
+ stmt.close
156
+ end
157
+
158
+ def execute_query(sql)
159
+ stmt = @connection.createStatement
160
+ unmarshal_result(stmt.executeQuery(sql))
161
+ ensure
162
+ stmt.close
163
+ end
164
+
165
+ def begin
166
+ @connection.setAutoCommit(false)
167
+ end
168
+
169
+ def commit
170
+ @connection.commit
171
+ ensure
172
+ @connection.setAutoCommit(true)
173
+ end
174
+
175
+ def rollback
176
+ @connection.rollback
177
+ ensure
178
+ @connection.setAutoCommit(true)
179
+ end
180
+
181
+ private
182
+ def unmarshal_result(resultset)
183
+ metadata = resultset.getMetaData
184
+ column_count = metadata.getColumnCount
185
+ column_names = ['']
186
+ column_types = ['']
187
+ column_scale = ['']
188
+
189
+ 1.upto(column_count) do |i|
190
+ column_names << metadata.getColumnName(i)
191
+ column_types << metadata.getColumnType(i)
192
+ column_scale << metadata.getScale(i)
193
+ end
194
+
195
+ results = []
196
+
197
+ while resultset.next
198
+ row = {}
199
+ 1.upto(column_count) do |i|
200
+ row[column_names[i].downcase] = convert_jdbc_type_to_ruby(i, column_types[i], column_scale[i], resultset)
201
+ end
202
+ results << row
203
+ end
204
+
205
+ results
206
+ end
207
+
208
+ def to_ruby_time(java_date)
209
+ if java_date
210
+ tm = java_date.getTime
211
+ Time.at(tm / 1000, (tm % 1000) * 1000)
212
+ end
213
+ end
214
+
215
+ def convert_jdbc_type_to_ruby(row, type, scale, resultset)
216
+ if scale != 0
217
+ decimal = resultset.getString(row)
218
+ decimal.to_f
219
+ else
220
+ case type
221
+ when Jdbc::Types::CHAR, Jdbc::Types::VARCHAR, Jdbc::Types::LONGVARCHAR
222
+ resultset.getString(row)
223
+ when Jdbc::Types::SMALLINT, Jdbc::Types::INTEGER, Jdbc::Types::NUMERIC, Jdbc::Types::BIGINT
224
+ resultset.getInt(row)
225
+ when Jdbc::Types::BIT, Jdbc::Types::BOOLEAN, Jdbc::Types::TINYINT
226
+ resultset.getBoolean(row)
227
+ when Jdbc::Types::TIMESTAMP
228
+ to_ruby_time(resultset.getTimestamp(row))
229
+ when Jdbc::Types::TIME
230
+ to_ruby_time(resultset.getTime(row))
231
+ when Jdbc::Types::DATE
232
+ to_ruby_time(resultset.getDate(row))
233
+ else
234
+ types = Jdbc::Types.constants
235
+ name = types.find {|t| Jdbc::Types.const_get(t.to_sym) == type}
236
+ raise "jdbc_adapter: type #{name} not supported yet"
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ class JdbcAdapter < AbstractAdapter
243
+ def initialize(connection, logger, config)
244
+ super(connection, logger)
245
+ @config = config
246
+ end
247
+
248
+ def adapter_name #:nodoc:
249
+ 'JDBC'
250
+ end
251
+
252
+ def supports_migrations?
253
+ true
254
+ end
255
+
256
+ def native_database_types #:nodoc
257
+ @connection.native_database_types
258
+ end
259
+
260
+ def active?
261
+ true
262
+ end
263
+
264
+ def reconnect!
265
+ @connection.close rescue nil
266
+ @connection = JdbcConnection.new(@config)
267
+ end
268
+
269
+ def select_all(sql, name = nil)
270
+ select(sql, name)
271
+ end
272
+
273
+ def select_one(sql, name = nil)
274
+ select(sql, name).first
275
+ end
276
+
277
+ def execute(sql, name = nil)
278
+ log_no_bench(sql, name) do
279
+ if sql =~ /^select/i
280
+ @connection.execute_query(sql)
281
+ else
282
+ @connection.execute_update(sql)
283
+ end
284
+ end
285
+ end
286
+
287
+ # Oracle doesn't support limit and offset. Fake it instead.
288
+ def add_limit_offset!(sql, options) #:nodoc:
289
+ if /oracle/ =~ @config[:driver]
290
+ offset = options[:offset] || 0
291
+
292
+ if limit = options[:limit]
293
+ sql.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_ where rownum <= #{offset+limit}) where raw_rnum_ > #{offset}"
294
+ elsif offset > 0
295
+ sql.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_) where raw_rnum_ > #{offset}"
296
+ end
297
+ else
298
+ super
299
+ end
300
+ end
301
+
302
+ alias :update :execute
303
+ alias :delete :execute
304
+
305
+ def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
306
+ log_no_bench(sql, name) do
307
+ id = @connection.execute_insert(sql, pk)
308
+ id_value || id
309
+ end
310
+ end
311
+
312
+ def columns(table_name, name = nil)
313
+ @connection.columns(table_name)
314
+ end
315
+
316
+ def tables
317
+ @connection.tables
318
+ end
319
+
320
+ def begin_db_transaction
321
+ @connection.begin
322
+ end
323
+
324
+ def commit_db_transaction
325
+ @connection.commit
326
+ end
327
+
328
+ def rollback_db_transaction
329
+ @connection.rollback
330
+ end
331
+
332
+ private
333
+ def select(sql, name)
334
+ log_no_bench(sql, name) { @connection.execute_query(sql) }
335
+ end
336
+
337
+ def log_no_bench(sql, name)
338
+ if block_given?
339
+ if @logger and @logger.level <= Logger::INFO
340
+ result = yield
341
+ log_info(sql, name, 0)
342
+ result
343
+ else
344
+ yield
345
+ end
346
+ else
347
+ log_info(sql, name, 0)
348
+ nil
349
+ end
350
+ rescue Exception => e
351
+ # Log message and raise exception.
352
+ message = "#{e.class.name}: #{e.message}: #{sql}"
353
+ log_info(message, name, 0)
354
+ raise ActiveRecord::StatementInvalid, message
355
+ end
356
+ end
357
+ end
358
+ end
@@ -0,0 +1,25 @@
1
+ print "Using native JDBC (MySQL)\n"
2
+ require_dependency 'fixtures/course'
3
+ require 'logger'
4
+
5
+ RAILS_CONNECTION_ADAPTERS << 'jdbc'
6
+ require "active_record/connection_adapters/jdbc_adapter"
7
+
8
+ ActiveRecord::Base.logger = Logger.new("debug.log")
9
+
10
+ db1 = 'activerecord_unittest'
11
+ db2 = 'activerecord_unittest2'
12
+
13
+ ActiveRecord::Base.establish_connection(
14
+ :adapter => "jdbc",
15
+ :driver => "com.mysql.jdbc.Driver",
16
+ :url => "jdbc:mysql://localhost:3306/#{db1}",
17
+ :username => "rails"
18
+ )
19
+
20
+ Course.establish_connection(
21
+ :adapter => "jdbc",
22
+ :driver => "com.mysql.jdbc.Driver",
23
+ :url => "jdbc:mysql://localhost:3306/#{db2}",
24
+ :username => "rails"
25
+ )
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ for test in *_test.rb; do
4
+ ./jtest.sh $test
5
+ done
6
+
7
+ #jruby.sh -I connections/native_jdbc_mysql -e 'Dir.foreach(".") { |file| require file if file =~ /_test.rb$/ }' | tee all.log
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ jruby.sh -I connections/native_jdbc_mysql $1 | tee $1.log
@@ -0,0 +1,109 @@
1
+
2
+ $silentTests = false
3
+ $testnum=0
4
+ $ntest=0
5
+ $failed = []
6
+ $curtestOK=true
7
+
8
+ module MiniRUnit
9
+ class Failure
10
+ def initialize(what, testnum, msg, where)
11
+ @what, @testnum, @msg, @where = what, testnum, msg, where
12
+ end
13
+
14
+ def to_s
15
+ sprintf("FAILED %s %d %s-- %s\n", @what, @testnum, @msg, @where)
16
+ end
17
+ end
18
+
19
+ class Error
20
+ def initialize(what, testnum, boom)
21
+ @what, @testnum, @boom = what, testnum, boom
22
+ end
23
+
24
+ def to_s
25
+ sprintf("EXCEPTION raised %s %d -- \n\tException: %s\n\t%s",
26
+ @what, @testnum, @boom.to_s, @boom.backtrace.join("\n\t"))
27
+ end
28
+ end
29
+ end
30
+
31
+
32
+ def test_check(what)
33
+ printf "%s : ", what unless $silentTests
34
+ $what = what
35
+ $testnum = 0
36
+ end
37
+
38
+ def test_ok(cond, msg="")
39
+ $testnum+=1
40
+ $ntest+=1
41
+ if cond
42
+ print "." unless $silentTests
43
+ else
44
+ where = caller.reject {|where| where =~ /minirunit/}[0]
45
+ $failed.push(MiniRUnit::Failure.new($what, $testnum, msg, where))
46
+ print "F" unless $silentTests
47
+ $curtestOK=false
48
+ end
49
+ end
50
+
51
+ def test_fail(msg="")
52
+ test_ok(false, msg)
53
+ end
54
+
55
+ def test_equal(a,b)
56
+ test_ok(a == b, "expected #{a.inspect}, found #{b.inspect}")
57
+ end
58
+
59
+ def test_no_exception(&proc)
60
+ raised = false
61
+ begin
62
+ proc.call
63
+ rescue exception
64
+ raised = x
65
+ end
66
+ test_ok(!raised, "unexpected exception #{raised}")
67
+ end
68
+
69
+ def test_exception(type=Exception, &proc)
70
+ raised = false
71
+ begin
72
+ proc.call
73
+ rescue type=>e
74
+ raised = true
75
+ end
76
+ test_ok(raised, "#{type} expected")
77
+ e
78
+ end
79
+
80
+ def test_get_last_failed
81
+ if $failed.empty?
82
+ return nil
83
+ end
84
+ return $failed.last
85
+ end
86
+
87
+ def test_print_report
88
+ puts
89
+ puts "-" * 80
90
+ $failed.each { |error| puts error }
91
+ puts "-" * 80
92
+ puts "Tests: #$ntest. (Ok: #{$ntest - $failed.size}; Failed: #{$failed.size})"
93
+ end
94
+
95
+ def test_load(test)
96
+ begin
97
+ $curtestOK=true
98
+ load(test)
99
+ rescue Exception => boom
100
+ puts 'ERROR' unless $silentTests
101
+ $failed.push(MiniRUnit::Error.new($what, $testnum, boom))
102
+ else
103
+ if $curtestOK
104
+ puts 'OK' unless $silentTests
105
+ else
106
+ puts 'FAILED' unless $silentTests
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,14 @@
1
+ require 'test/minirunit'
2
+ RAILS_CONNECTION_ADAPTERS = ['abstract', 'jdbc']
3
+ require 'active_record'
4
+
5
+ connspec = ActiveRecord::Base.establish_connection(
6
+ :adapter => 'jdbc',
7
+ :driver => 'com.mysql.jdbc.Driver',
8
+ :url => 'jdbc:mysql://localhost:3306/test',
9
+ :username => 'rlsmgr',
10
+ :password => ''
11
+ )
12
+
13
+ puts "#{connspec}"
14
+ puts "#{ActiveRecord::Base.connection}"
@@ -0,0 +1,71 @@
1
+ # To run this script, run the following in a mysql instance:
2
+ #
3
+ # drop database if exists weblog_development;
4
+ # create database weblog_development;
5
+ # grant all on weblog_development.* to blog@localhost;
6
+
7
+ require 'test/minirunit'
8
+
9
+ config = {
10
+ :adapter => 'jdbc',
11
+ :username => 'sa',
12
+ :password => '',
13
+ :driver => 'org.hsqldb.jdbcDriver',
14
+ :url => 'jdbc:hsqldb:test.db'
15
+ }
16
+
17
+ require 'active_record'
18
+
19
+ ActiveRecord::Base.establish_connection(config)
20
+
21
+ class CreateEntries < ActiveRecord::Migration
22
+ def self.up
23
+ create_table "entries", :force => true do |t|
24
+ t.column :title, :string, :limit => 100
25
+ t.column :updated_on, :datetime
26
+ t.column :content, :text
27
+ end
28
+ end
29
+
30
+ def self.down
31
+ drop_table "entries"
32
+ end
33
+ end
34
+
35
+ CreateEntries.up
36
+
37
+ test_ok ActiveRecord::Base.connection.tables.include?('entries')
38
+
39
+ class Entry < ActiveRecord::Base
40
+ end
41
+
42
+ Entry.delete_all
43
+
44
+ test_equal 0, Entry.count
45
+
46
+ TITLE = "First post!"
47
+ CONTENT = "Hello from JRuby on Rails!"
48
+ NEW_TITLE = "First post updated title"
49
+
50
+ post = Entry.new
51
+ post.title = TITLE
52
+ post.content = CONTENT
53
+ post.save
54
+
55
+ test_equal 1, Entry.count
56
+
57
+ post = Entry.find(:first)
58
+ test_equal TITLE, post.title
59
+ test_equal CONTENT, post.content
60
+
61
+ post.title = NEW_TITLE
62
+ post.save
63
+
64
+ post = Entry.find(:first)
65
+ test_equal NEW_TITLE, post.title
66
+
67
+ post.destroy
68
+
69
+ test_equal 0, Entry.count
70
+
71
+ CreateEntries.down
@@ -0,0 +1,3 @@
1
+ require 'test/minirunit'
2
+ RAILS_CONNECTION_ADAPTERS = ['abstract']
3
+ test_load 'active_record'
@@ -0,0 +1,83 @@
1
+ # To run this script, run the following in a mysql instance:
2
+ #
3
+ # drop database if exists weblog_development;
4
+ # create database weblog_development;
5
+ # grant all on weblog_development.* to blog@localhost;
6
+
7
+ require 'test/minirunit'
8
+
9
+ config = {
10
+ :username => 'blog',
11
+ :password => ''
12
+ }
13
+
14
+ if RUBY_PLATFORM =~ /java/
15
+ RAILS_CONNECTION_ADAPTERS = ['abstract', 'jdbc']
16
+ config.update({
17
+ :adapter => 'jdbc',
18
+ :driver => 'com.mysql.jdbc.Driver',
19
+ :url => 'jdbc:mysql://localhost:3306/weblog_development',
20
+ })
21
+ else
22
+ config.update({
23
+ :adapter => 'mysql',
24
+ :database => 'weblog_development',
25
+ :host => 'localhost'
26
+ })
27
+ end
28
+
29
+ require 'active_record'
30
+
31
+ ActiveRecord::Base.establish_connection(config)
32
+
33
+ class CreateEntries < ActiveRecord::Migration
34
+ def self.up
35
+ create_table "entries", :force => true do |t|
36
+ t.column :title, :string, :limit => 100
37
+ t.column :updated_on, :datetime
38
+ t.column :content, :text
39
+ end
40
+ end
41
+
42
+ def self.down
43
+ drop_table "entries"
44
+ end
45
+ end
46
+
47
+ CreateEntries.up
48
+
49
+ test_ok ActiveRecord::Base.connection.tables.include?('entries')
50
+
51
+ class Entry < ActiveRecord::Base
52
+ end
53
+
54
+ Entry.delete_all
55
+
56
+ test_equal 0, Entry.count
57
+
58
+ TITLE = "First post!"
59
+ CONTENT = "Hello from JRuby on Rails!"
60
+ NEW_TITLE = "First post updated title"
61
+
62
+ post = Entry.new
63
+ post.title = TITLE
64
+ post.content = CONTENT
65
+ post.save
66
+
67
+ test_equal 1, Entry.count
68
+
69
+ post = Entry.find(:first)
70
+ test_equal TITLE, post.title
71
+ test_equal CONTENT, post.content
72
+
73
+ post.title = NEW_TITLE
74
+ post.save
75
+
76
+ post = Entry.find(:first)
77
+ test_equal NEW_TITLE, post.title
78
+
79
+ post.destroy
80
+
81
+ test_equal 0, Entry.count
82
+
83
+ CreateEntries.down
@@ -0,0 +1,24 @@
1
+
2
+ require 'test/minirunit'
3
+ RAILS_CONNECTION_ADAPTERS = ['abstract', 'jdbc']
4
+ require 'active_record'
5
+
6
+ connspec = ActiveRecord::Base.establish_connection(
7
+ :adapter => 'jdbc',
8
+ :driver => 'com.mysql.jdbc.Driver',
9
+ :url => 'jdbc:mysql://localhost:3306/weblog_development',
10
+ :username => 'blog',
11
+ :password => ''
12
+ )
13
+
14
+ connection = ActiveRecord::Base.connection
15
+
16
+ results = connection.execute "select * from entries"
17
+
18
+ test_equal results.length, 1
19
+
20
+ row = results.first
21
+ test_equal 'First post', row['title']
22
+ test_equal 'First post d00d!', row['content']
23
+
24
+ puts row.inspect
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: ActiveRecord-JDBC
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2006-08-07 00:00:00 +02:00
8
+ summary: JDBC support for ActiveRecord. Only usable within JRuby
9
+ require_paths:
10
+ - lib
11
+ email: ola@ologix.com
12
+ homepage: http://jruby-extras.rubyforge.org/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: active_record/connection_adapters/jdbc_adapter
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - JRuby-extras
30
+ files:
31
+ - lib/active_record
32
+ - lib/active_record/connection_adapters
33
+ - lib/active_record/connection_adapters/jdbc_adapter.rb
34
+ - test/activerecord
35
+ - test/minirunit
36
+ - test/minirunit.rb
37
+ - test/activerecord/connections
38
+ - test/activerecord/jall.sh
39
+ - test/activerecord/jtest.sh
40
+ - test/activerecord/connections/native_jdbc_mysql
41
+ - test/activerecord/connections/native_jdbc_mysql/connection.rb
42
+ - test/minirunit/testConnect.rb
43
+ - test/minirunit/testHsqldb.rb
44
+ - test/minirunit/testLoadActiveRecord.rb
45
+ - test/minirunit/testMysql.rb
46
+ - test/minirunit/testRawSelect.rb
47
+ - LICENSE
48
+ - init.rb
49
+ - install.rb
50
+ test_files: []
51
+
52
+ rdoc_options: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ requirements: []
61
+
62
+ dependencies: []
63
+