activerecord-jdbc-adapter 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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)