activerecord-jdbc-adapter 0.9.1 → 0.9.2

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 (52) hide show
  1. data/History.txt +33 -0
  2. data/Manifest.txt +17 -0
  3. data/README.txt +48 -20
  4. data/Rakefile +2 -169
  5. data/lib/active_record/connection_adapters/jdbc_adapter.rb +11 -5
  6. data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +12 -0
  7. data/lib/jdbc_adapter.rb +1 -1
  8. data/lib/jdbc_adapter/jdbc.rake +43 -30
  9. data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
  10. data/lib/jdbc_adapter/jdbc_db2.rb +2 -2
  11. data/lib/jdbc_adapter/jdbc_derby.rb +11 -0
  12. data/lib/jdbc_adapter/jdbc_hsqldb.rb +6 -1
  13. data/lib/jdbc_adapter/jdbc_mimer.rb +14 -7
  14. data/lib/jdbc_adapter/jdbc_mssql.rb +18 -2
  15. data/lib/jdbc_adapter/jdbc_mysql.rb +3 -0
  16. data/lib/jdbc_adapter/jdbc_oracle.rb +24 -14
  17. data/lib/jdbc_adapter/jdbc_postgre.rb +38 -18
  18. data/lib/jdbc_adapter/jdbc_sqlite3.rb +96 -26
  19. data/lib/jdbc_adapter/missing_functionality_helper.rb +40 -34
  20. data/lib/jdbc_adapter/rake_tasks.rb +1 -1
  21. data/lib/jdbc_adapter/tsql_helper.rb +1 -0
  22. data/lib/jdbc_adapter/version.rb +1 -1
  23. data/lib/pg.rb +4 -0
  24. data/rails_generators/jdbc_generator.rb +15 -0
  25. data/rails_generators/templates/jdbc.rake +8 -0
  26. data/rails_generators/templates/jdbc.rb +7 -0
  27. data/rakelib/compile.rake +23 -0
  28. data/rakelib/package.rake +85 -0
  29. data/rakelib/rails.rake +41 -0
  30. data/rakelib/test.rake +71 -0
  31. data/src/java/jdbc_adapter/JdbcAdapterInternalService.java +1 -0
  32. data/src/java/jdbc_adapter/JdbcDerbySpec.java +11 -46
  33. data/src/java/jdbc_adapter/JdbcMySQLSpec.java +3 -2
  34. data/src/java/jdbc_adapter/MssqlRubyJdbcConnection.java +71 -0
  35. data/src/java/jdbc_adapter/PostgresRubyJdbcConnection.java +24 -4
  36. data/src/java/jdbc_adapter/RubyJdbcConnection.java +57 -44
  37. data/test/abstract_db_create.rb +45 -0
  38. data/test/db/mysql.rb +2 -2
  39. data/test/db/postgres.rb +2 -2
  40. data/test/helper.rb +5 -0
  41. data/test/jdbc_adapter/jdbc_db2_test.rb +5 -0
  42. data/test/jdbc_common.rb +2 -0
  43. data/test/models/entry.rb +3 -0
  44. data/test/models/validates_uniqueness_of_string.rb +19 -0
  45. data/test/mysql_db_create_test.rb +25 -0
  46. data/test/mysql_nonstandard_primary_key_test.rb +42 -0
  47. data/test/mysql_simple_test.rb +5 -0
  48. data/test/postgres_db_create_test.rb +21 -0
  49. data/test/postgres_nonseq_pkey_test.rb +40 -0
  50. data/test/simple.rb +62 -1
  51. data/test/sqlite3_simple_test.rb +153 -10
  52. metadata +26 -5
data/test/db/mysql.rb CHANGED
@@ -1,4 +1,4 @@
1
- config = {
1
+ MYSQL_CONFIG = {
2
2
  :username => 'blog',
3
3
  :password => '',
4
4
  :adapter => 'mysql',
@@ -6,5 +6,5 @@ config = {
6
6
  :host => 'localhost'
7
7
  }
8
8
 
9
- ActiveRecord::Base.establish_connection(config)
9
+ ActiveRecord::Base.establish_connection(MYSQL_CONFIG)
10
10
 
data/test/db/postgres.rb CHANGED
@@ -1,4 +1,4 @@
1
- config = {
1
+ POSTGRES_CONFIG = {
2
2
  :adapter => 'postgresql',
3
3
  :database => 'weblog_development',
4
4
  :host => 'localhost',
@@ -6,4 +6,4 @@ config = {
6
6
  :password => ''
7
7
  }
8
8
 
9
- ActiveRecord::Base.establish_connection(config)
9
+ ActiveRecord::Base.establish_connection(POSTGRES_CONFIG)
data/test/helper.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Kernel
2
+ def find_executable?(name)
3
+ ENV['PATH'].split(File::PATH_SEPARATOR).detect {|p| File.executable?(File.join(p, name))}
4
+ end
5
+ end
@@ -18,4 +18,9 @@ class JdbcSpec::DB2Test < Test::Unit::TestCase
18
18
  assert_equal %q{123.45}, @inst.quote("123.45", @column), "decimal columns should not have quotes"
19
19
  end
20
20
 
21
+ def test_primary_key_generation
22
+ @column.type = :primary_key
23
+ assert_equal 'int not null generated by default as identity (start with 1) primary key', @inst.modify_types({:string => {}, :integer => {}, :boolean => {}})[:primary_key]
24
+ end
25
+
21
26
  end
data/test/jdbc_common.rb CHANGED
@@ -14,8 +14,10 @@ require 'models/auto_id'
14
14
  require 'models/entry'
15
15
  require 'models/data_types'
16
16
  require 'models/add_not_null_column_to_table'
17
+ require 'models/validates_uniqueness_of_string'
17
18
  require 'simple'
18
19
  require 'has_many_through'
20
+ require 'helper'
19
21
  require 'test/unit'
20
22
 
21
23
  # Comment/uncomment to enable logging to be loaded for any of the database adapters
data/test/models/entry.rb CHANGED
@@ -17,4 +17,7 @@ class CreateEntries < ActiveRecord::Migration
17
17
  end
18
18
 
19
19
  class Entry < ActiveRecord::Base
20
+ def to_param
21
+ "#{id}-#{title.gsub(/[^a-zA-Z0-9]/, '-')}"
22
+ end
20
23
  end
@@ -0,0 +1,19 @@
1
+ class CreateValidatesUniquenessOf < ActiveRecord::Migration
2
+ def self.up
3
+ create_table "validates_uniqueness_of", :force => true do |t|
4
+ t.column :cs_string, :string
5
+ t.column :ci_string, :string
6
+ t.column :content, :text
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table "validates_uniqueness_of"
12
+ end
13
+ end
14
+
15
+ class ValidatesUniquenessOfString < ActiveRecord::Base
16
+ self.set_table_name "validates_uniqueness_of"
17
+ validates_uniqueness_of :cs_string, :case_sensitive => true
18
+ validates_uniqueness_of :ci_string, :case_sensitive => false
19
+ end
@@ -0,0 +1,25 @@
1
+ require 'abstract_db_create'
2
+ require 'db/mysql'
3
+
4
+ class MysqlDbCreateTest < Test::Unit::TestCase
5
+ include AbstractDbCreate
6
+
7
+ def db_config
8
+ MYSQL_CONFIG
9
+ end
10
+
11
+ if find_executable?("mysql")
12
+ def test_rake_db_create
13
+ Rake::Task["db:create"].invoke
14
+ output = nil
15
+ IO.popen("mysql -u #{MYSQL_CONFIG[:username]} --password=#{MYSQL_CONFIG[:password]}", "r+") do |mysql|
16
+ mysql << "show databases where `Database` = '#{@db_name}';"
17
+ mysql.close_write
18
+ assert mysql.read =~ /#{@db_name}/m
19
+ end
20
+ end
21
+ else
22
+ def test_skipped
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,42 @@
1
+ require 'jdbc_common'
2
+ require 'db/mysql'
3
+
4
+ class Project < ActiveRecord::Migration
5
+ def self.up
6
+ create_table :project, :primary_key => "project_id" do |t|
7
+ t.string :projectType, :limit => 31
8
+ t.boolean :published
9
+ t.datetime :created_date
10
+ t.text :abstract, :title
11
+ end
12
+ end
13
+
14
+ def self.down
15
+ drop_table :project
16
+ end
17
+
18
+ end
19
+
20
+ class MysqlNonstandardPrimaryKeyTest < Test::Unit::TestCase
21
+
22
+ def setup
23
+ Project.up
24
+ end
25
+
26
+ def teardown
27
+ Project.down
28
+ end
29
+
30
+ def standard_dump
31
+ stream = StringIO.new
32
+ ActiveRecord::SchemaDumper.ignore_tables = []
33
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
34
+ stream.string
35
+ end
36
+
37
+ def test_nonstandard_primary_key
38
+ output = standard_dump
39
+ assert_match %r(:primary_key => "project_id"), output, "non-standard primary key not preserved"
40
+ end
41
+
42
+ end
@@ -19,6 +19,11 @@ class MysqlSimpleTest < Test::Unit::TestCase
19
19
  assert_equal "a'a", s2
20
20
  assert_equal "'a\\'a'", ActiveRecord::Base.connection.quote(s2)
21
21
  end
22
+
23
+ def test_table_name_quoting_with_dot
24
+ s = "weblog_development.posts"
25
+ assert_equal "`weblog_development`.`posts`", ActiveRecord::Base.connection.quote_table_name(s)
26
+ end
22
27
  end
23
28
 
24
29
  class MysqlHasManyThroughTest < Test::Unit::TestCase
@@ -0,0 +1,21 @@
1
+ require 'abstract_db_create'
2
+ require 'db/postgres'
3
+
4
+ class PostgresDbCreateTest < Test::Unit::TestCase
5
+ include AbstractDbCreate
6
+
7
+ def db_config
8
+ POSTGRES_CONFIG
9
+ end
10
+
11
+ if find_executable?("psql")
12
+ def test_rake_db_create
13
+ Rake::Task["db:create"].invoke
14
+ output = `psql -c '\\l'`
15
+ assert output =~ /#{@db_name}/m
16
+ end
17
+ else
18
+ def test_skipped
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'jdbc_common'
4
+ require 'db/postgres'
5
+
6
+ class CreateUrls < ActiveRecord::Migration
7
+ def self.up
8
+ create_table 'urls', :id => false do |t|
9
+ t.text :uhash, :null => false
10
+ t.text :url, :null => false
11
+ end
12
+ execute "ALTER TABLE urls ADD PRIMARY KEY (uhash)"
13
+ end
14
+ def self.down
15
+ drop_table 'urls'
16
+ end
17
+ end
18
+
19
+ class Url < ActiveRecord::Base
20
+ set_primary_key :uhash
21
+ #Shouldn't be needed: set_sequence_name nil
22
+ end
23
+
24
+ class PostgresNonSeqPKey < Test::Unit::TestCase
25
+ def setup
26
+ CreateUrls.up
27
+ end
28
+
29
+ def teardown
30
+ CreateUrls.down
31
+ end
32
+
33
+ def test_create
34
+ url = Url.create! do |u|
35
+ u.uhash = 'uhash'
36
+ u.url = 'http://url'
37
+ end
38
+ assert_equal( 'uhash', url.uhash )
39
+ end
40
+ end
data/test/simple.rb CHANGED
@@ -10,6 +10,7 @@ module MigrationSetup
10
10
  DbTypeMigration.up
11
11
  CreateEntries.up
12
12
  CreateAutoIds.up
13
+ CreateValidatesUniquenessOf.up
13
14
 
14
15
  @connection = ActiveRecord::Base.connection
15
16
  end
@@ -18,6 +19,7 @@ module MigrationSetup
18
19
  DbTypeMigration.down
19
20
  CreateEntries.down
20
21
  CreateAutoIds.down
22
+ CreateValidatesUniquenessOf.down
21
23
  ActiveRecord::Base.clear_active_connections!
22
24
  end
23
25
  end
@@ -47,6 +49,12 @@ module SimpleTestMethods
47
49
  assert_equal 0, Entry.count
48
50
  end
49
51
 
52
+ def test_find_with_string_slug
53
+ new_entry = Entry.create(:title => "Blah")
54
+ entry = Entry.find(new_entry.to_param)
55
+ assert_equal new_entry.id, entry.id
56
+ end
57
+
50
58
  def test_insert_returns_id
51
59
  unless ActiveRecord::Base.connection.adapter_name =~ /oracle/i
52
60
  value = ActiveRecord::Base.connection.insert("INSERT INTO entries (title, content, rating) VALUES('insert_title', 'some content', 1)")
@@ -160,7 +168,7 @@ module SimpleTestMethods
160
168
  e = DbType.find(:first)
161
169
  assert_equal(true, e.sample_boolean)
162
170
  end
163
-
171
+
164
172
  def test_integer
165
173
  # An unset boolean should default to nil
166
174
  e = DbType.find(:first)
@@ -294,6 +302,59 @@ module SimpleTestMethods
294
302
  AddNotNullColumnToTable.down
295
303
  end
296
304
 
305
+ def test_validates_uniqueness_of_strings_case_sensitive
306
+ # MySQL string cmps are case-insensitive by default, so skip this test
307
+ return if ActiveRecord::Base.connection.config[:adapter] =~ /mysql/
308
+
309
+ name_lower = ValidatesUniquenessOfString.new(:cs_string => "name", :ci_string => '1')
310
+ name_lower.save!
311
+
312
+ name_upper = ValidatesUniquenessOfString.new(:cs_string => "NAME", :ci_string => '2')
313
+ assert_nothing_raised do
314
+ name_upper.save!
315
+ end
316
+
317
+ name_lower_collision = ValidatesUniquenessOfString.new(:cs_string => "name", :ci_string => '3')
318
+ assert_raise ActiveRecord::RecordInvalid do
319
+ name_lower_collision.save!
320
+ end
321
+
322
+ name_upper_collision = ValidatesUniquenessOfString.new(:cs_string => "NAME", :ci_string => '4')
323
+ assert_raise ActiveRecord::RecordInvalid do
324
+ name_upper_collision.save!
325
+ end
326
+ end
327
+
328
+ def test_validates_uniqueness_of_strings_case_insensitive
329
+ name_lower = ValidatesUniquenessOfString.new(:cs_string => '1', :ci_string => "name")
330
+ name_lower.save!
331
+
332
+ name_upper = ValidatesUniquenessOfString.new(:cs_string => '2', :ci_string => "NAME")
333
+ assert_raise ActiveRecord::RecordInvalid do
334
+ name_upper.save!
335
+ end
336
+
337
+ name_lower_collision = ValidatesUniquenessOfString.new(:cs_string => '3', :ci_string => "name")
338
+ assert_raise ActiveRecord::RecordInvalid do
339
+ name_lower_collision.save!
340
+ end
341
+
342
+ alternate_name_upper = ValidatesUniquenessOfString.new(:cs_string => '4', :ci_string => "ALTERNATE_NAME")
343
+ assert_nothing_raised do
344
+ alternate_name_upper.save!
345
+ end
346
+
347
+ alternate_name_upper_collision = ValidatesUniquenessOfString.new(:cs_string => '5', :ci_string => "ALTERNATE_NAME")
348
+ assert_raise ActiveRecord::RecordInvalid do
349
+ alternate_name_upper_collision.save!
350
+ end
351
+
352
+ alternate_name_lower = ValidatesUniquenessOfString.new(:cs_string => '6', :ci_string => "alternate_name")
353
+ assert_raise ActiveRecord::RecordInvalid do
354
+ alternate_name_lower.save!
355
+ end
356
+ end
357
+
297
358
  class ChangeEntriesTable < ActiveRecord::Migration
298
359
  def self.up
299
360
  change_table :entries do |t|
@@ -1,10 +1,11 @@
1
1
  require 'jdbc_common'
2
2
  require 'db/sqlite3'
3
3
  require 'models/data_types'
4
+ require 'models/validates_uniqueness_of_string'
4
5
 
5
6
  class SQLite3SimpleTest < Test::Unit::TestCase
6
7
  include SimpleTestMethods
7
-
8
+
8
9
  def test_recreate_database
9
10
  assert @connection.tables.include?(Entry.table_name)
10
11
  db = @connection.database_name
@@ -12,27 +13,169 @@ class SQLite3SimpleTest < Test::Unit::TestCase
12
13
  assert (not @connection.tables.include? Entry.table_name)
13
14
  self.setup # avoid teardown complaining
14
15
  end
15
-
16
+
16
17
  def test_execute_insert
17
18
  assert_equal 1, Entry.count
18
19
  id = @connection.execute "INSERT INTO entries (title, content) VALUES ('Execute Insert', 'This now works with SQLite3')"
19
20
  assert_equal Entry.last.id, id
20
21
  assert_equal 2, Entry.count
21
22
  end
22
-
23
+
23
24
  def test_execute_update
24
25
  affected_rows = @connection.execute "UPDATE entries SET title = 'Execute Update' WHERE id = #{Entry.first.id}"
25
- assert_equal 1, affected_rows
26
+ assert_equal 1, affected_rows
26
27
  assert_equal 'Execute Update', Entry.first.title
27
28
  end
28
-
29
+
29
30
  def test_columns
30
31
  cols = ActiveRecord::Base.connection.columns("entries")
31
32
  assert cols.find {|col| col.name == "title"}
32
33
  end
33
-
34
+
35
+ def test_remove_column
36
+ assert_nothing_raised do
37
+ ActiveRecord::Schema.define do
38
+ add_column "entries", "test_remove_column", :string
39
+ end
40
+ end
41
+
42
+ cols = ActiveRecord::Base.connection.columns("entries")
43
+ assert cols.find {|col| col.name == "test_remove_column"}
44
+
45
+ assert_nothing_raised do
46
+ ActiveRecord::Schema.define do
47
+ remove_column "entries", "test_remove_column"
48
+ end
49
+ end
50
+
51
+ cols = ActiveRecord::Base.connection.columns("entries")
52
+ assert !cols.find {|col| col.name == "test_remove_column"}
53
+ end
54
+
55
+ def test_rename_column
56
+ assert_nothing_raised do
57
+ ActiveRecord::Schema.define do
58
+ rename_column "entries", "title", "name"
59
+ end
60
+ end
61
+
62
+ cols = ActiveRecord::Base.connection.columns("entries")
63
+ assert cols.find {|col| col.name == "name"}
64
+ assert !cols.find {|col| col.name == "title"}
65
+
66
+ assert_nothing_raised do
67
+ ActiveRecord::Schema.define do
68
+ rename_column "entries", "name", "title"
69
+ end
70
+ end
71
+
72
+ cols = ActiveRecord::Base.connection.columns("entries")
73
+ assert cols.find {|col| col.name == "title"}
74
+ assert !cols.find {|col| col.name == "name"}
75
+ end
76
+
77
+ def test_rename_column_preserves_content
78
+ post = Entry.find(:first)
79
+ assert_equal @title, post.title
80
+ assert_equal @content, post.content
81
+ assert_equal @rating, post.rating
82
+
83
+ assert_nothing_raised do
84
+ ActiveRecord::Schema.define do
85
+ rename_column "entries", "title", "name"
86
+ end
87
+ end
88
+
89
+ post = Entry.find(:first)
90
+ assert_equal @title, post.name
91
+ assert_equal @content, post.content
92
+ assert_equal @rating, post.rating
93
+ end
94
+
95
+ def test_rename_column_preserves_index
96
+ assert_equal(0, @connection.indexes(:entries).size)
97
+
98
+ index_name = "entries_index"
99
+
100
+ assert_nothing_raised do
101
+ ActiveRecord::Schema.define do
102
+ add_index "entries", "title", :name => index_name
103
+ end
104
+ end
105
+
106
+ indexes = @connection.indexes(:entries)
107
+ assert_equal(1, indexes.size)
108
+ assert_equal "entries", indexes.first.table.to_s
109
+ assert_equal index_name, indexes.first.name
110
+ assert !indexes.first.unique
111
+ assert_equal ["title"], indexes.first.columns
112
+
113
+ assert_nothing_raised do
114
+ ActiveRecord::Schema.define do
115
+ rename_column "entries", "title", "name"
116
+ end
117
+ end
118
+
119
+ indexes = @connection.indexes(:entries)
120
+ assert_equal(1, indexes.size)
121
+ assert_equal "entries", indexes.first.table.to_s
122
+ assert_equal index_name, indexes.first.name
123
+ assert !indexes.first.unique
124
+ assert_equal ["name"], indexes.first.columns
125
+ end
126
+
127
+ def test_change_column_default
128
+ assert_nothing_raised do
129
+ ActiveRecord::Schema.define do
130
+ add_column "entries", "test_change_column_default", :string, :default => "unchanged"
131
+ end
132
+ end
133
+
134
+ cols = ActiveRecord::Base.connection.columns("entries")
135
+ col = cols.find{|col| col.name == "test_change_column_default"}
136
+ assert col
137
+ assert_equal col.default, 'unchanged'
138
+
139
+ assert_nothing_raised do
140
+ ActiveRecord::Schema.define do
141
+ change_column_default "entries", "test_change_column_default", "changed"
142
+ end
143
+ end
144
+
145
+ cols = ActiveRecord::Base.connection.columns("entries")
146
+ col = cols.find{|col| col.name == "test_change_column_default"}
147
+ assert col
148
+ assert_equal col.default, 'changed'
149
+ end
150
+
151
+ def test_change_column
152
+ assert_nothing_raised do
153
+ ActiveRecord::Schema.define do
154
+ add_column "entries", "test_change_column", :string
155
+ end
156
+ end
157
+
158
+ cols = ActiveRecord::Base.connection.columns("entries")
159
+ col = cols.find{|col| col.name == "test_change_column"}
160
+ assert col
161
+ assert_equal col.type, :string
162
+
163
+ assert_nothing_raised do
164
+ ActiveRecord::Schema.define do
165
+ change_column "entries", "test_change_column", :integer
166
+ end
167
+ end
168
+
169
+ cols = ActiveRecord::Base.connection.columns("entries")
170
+ col = cols.find{|col| col.name == "test_change_column"}
171
+ assert col
172
+ assert_equal col.type, :integer
173
+ end
174
+
34
175
  end
35
-
176
+
177
+ # assert_raise ActiveRecord::RecordInvalid do
178
+
36
179
  class SQLite3HasManyThroughTest < Test::Unit::TestCase
37
180
  include HasManyThroughMethods
38
181
  end
@@ -42,7 +185,7 @@ if jruby?
42
185
  else
43
186
  JInteger = Fixnum
44
187
  class Fixnum
45
- # Arbitrary value...we could pick
188
+ # Arbitrary value...we could pick
46
189
  MAX_VALUE = 2
47
190
  end
48
191
  end
@@ -51,7 +194,7 @@ class SQLite3TypeConversionTest < Test::Unit::TestCase
51
194
  TEST_TIME = Time.at(1169964202)
52
195
  TEST_BINARY = "Some random binary data % \0 and then some"
53
196
  def setup
54
- DbTypeMigration.up
197
+ DbTypeMigration.up
55
198
  DbType.create(
56
199
  :sample_timestamp => TEST_TIME,
57
200
  :sample_datetime => TEST_TIME,
@@ -80,7 +223,7 @@ class SQLite3TypeConversionTest < Test::Unit::TestCase
80
223
  types = DbType.find(:first)
81
224
  assert_equal(3, DbType.columns_hash["sample_small_decimal"].precision)
82
225
  end
83
-
226
+
84
227
  def test_binary
85
228
  types = DbType.find(:first)
86
229
  assert_equal(TEST_BINARY, types.sample_binary)