activerecord-jdbc-adapter 1.2.8 → 1.2.9

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 (55) hide show
  1. data/.travis.yml +1 -1
  2. data/Gemfile +2 -1
  3. data/Gemfile.lock +5 -6
  4. data/History.txt +11 -0
  5. data/gemfiles/rails23.gemfile +2 -1
  6. data/gemfiles/rails23.gemfile.lock +5 -2
  7. data/gemfiles/rails30.gemfile +2 -1
  8. data/gemfiles/rails30.gemfile.lock +5 -2
  9. data/gemfiles/rails31.gemfile +2 -1
  10. data/gemfiles/rails31.gemfile.lock +5 -2
  11. data/gemfiles/rails32.gemfile +2 -1
  12. data/gemfiles/rails32.gemfile.lock +5 -2
  13. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +1 -1
  14. data/lib/arel/visitors/sql_server.rb +4 -4
  15. data/lib/arjdbc/db2/adapter.rb +14 -3
  16. data/lib/arjdbc/discover.rb +1 -1
  17. data/lib/arjdbc/jdbc/adapter.rb +1 -0
  18. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  19. data/lib/arjdbc/jdbc/connection.rb +73 -63
  20. data/lib/arjdbc/jdbc/extension.rb +1 -1
  21. data/lib/arjdbc/mssql.rb +3 -0
  22. data/lib/arjdbc/mssql/adapter.rb +132 -115
  23. data/lib/arjdbc/mssql/connection_methods.rb +1 -1
  24. data/lib/arjdbc/mssql/limit_helpers.rb +62 -66
  25. data/lib/arjdbc/mssql/lock_helpers.rb +2 -2
  26. data/lib/arjdbc/mssql/tsql_methods.rb +58 -0
  27. data/lib/arjdbc/mssql/utils.rb +53 -0
  28. data/lib/arjdbc/oracle/adapter.rb +61 -39
  29. data/lib/arjdbc/sqlite3/adapter.rb +3 -6
  30. data/lib/arjdbc/version.rb +1 -1
  31. data/src/java/arjdbc/jdbc/AdapterJavaService.java +4 -2
  32. data/src/java/arjdbc/mssql/MSSQLModule.java +70 -0
  33. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +128 -0
  34. data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +25 -112
  35. data/test/db/mssql.rb +8 -8
  36. data/test/db2_simple_test.rb +7 -0
  37. data/test/models/entry.rb +2 -1
  38. data/test/mssql_binary_test.rb +6 -0
  39. data/test/mssql_db_create_test.rb +5 -2
  40. data/test/mssql_identity_insert_test.rb +1 -2
  41. data/test/mssql_ignore_system_views_test.rb +5 -5
  42. data/test/mssql_limit_offset_test.rb +51 -55
  43. data/test/mssql_multibyte_test.rb +1 -2
  44. data/test/mssql_row_locking_test.rb +1 -1
  45. data/test/mssql_simple_test.rb +6 -10
  46. data/test/{mssql_row_locking_sql_test.rb → mssql_test.rb} +110 -18
  47. data/test/mysql_db_create_test.rb +13 -7
  48. data/test/oracle_simple_test.rb +18 -0
  49. data/test/postgres_db_create_test.rb +26 -13
  50. data/test/simple.rb +45 -15
  51. data/test/sqlite3_schema_dump_test.rb +6 -0
  52. data/test/sqlite3_type_conversion_test.rb +20 -17
  53. data/test/test_helper.rb +44 -2
  54. metadata +9 -4
  55. data/lib/arjdbc/mssql/tsql_helper.rb +0 -53
@@ -1,8 +1,100 @@
1
- require 'arjdbc/mssql/adapter'
2
- require 'test/unit'
1
+ require 'test_helper'
2
+ require 'arjdbc/mssql'
3
+
4
+ class MSSQLTest < Test::Unit::TestCase
5
+
6
+ # NOTE: lot of tests kindly borrowed from __activerecord-sqlserver-adapter__
7
+
8
+ test "get table name" do
9
+ insert_sql = "INSERT INTO [funny_jokes] ([name]) VALUES('Knock knock')"
10
+ update_sql = "UPDATE [customers] SET [address_street] = NULL WHERE [id] = 2"
11
+ select_sql = "SELECT * FROM [customers] WHERE ([customers].[id] = 1)"
12
+
13
+ connection = new_adapter_stub
14
+ assert_equal 'funny_jokes', connection.send(:get_table_name, insert_sql)
15
+ assert_equal 'customers', connection.send(:get_table_name, update_sql)
16
+ assert_equal 'customers', connection.send(:get_table_name, select_sql)
17
+
18
+ assert_equal '[funny_jokes]', connection.send(:get_table_name, insert_sql, true)
19
+ assert_equal '[customers]', connection.send(:get_table_name, update_sql, true)
20
+ assert_equal '[customers]', connection.send(:get_table_name, select_sql, true)
21
+
22
+ select_sql = " SELECT * FROM customers WHERE ( customers.id = 1 ) "
23
+ assert_equal 'customers', connection.send(:get_table_name, select_sql)
24
+ assert_equal 'customers', connection.send(:get_table_name, select_sql, true)
25
+
26
+ assert_nil connection.send(:get_table_name, 'SELECT 1')
27
+ # NOTE: this has been failing even before refactoring - not sure if it's needed :
28
+ #assert_nil connection.send(:get_table_name, 'SELECT * FROM someFunction()')
29
+ #assert_nil connection.send(:get_table_name, 'SELECT * FROM someFunction() WHERE 1 > 2')
30
+ end
31
+
32
+ context "Utils" do
33
+
34
+ setup do
35
+ @expected_table_name = 'baz'
36
+ @expected_db_name = 'foo'
37
+ @first_second_table_names = ['[baz]','baz','[bar].[baz]','bar.baz']
38
+ @third_table_names = ['[foo].[bar].[baz]','foo.bar.baz']
39
+ @qualifed_table_names = @first_second_table_names + @third_table_names
40
+ end
41
+
42
+ test 'return clean table_name from Utils.unqualify_table_name' do
43
+ @qualifed_table_names.each do |qtn|
44
+ assert_equal @expected_table_name,
45
+ ArJdbc::MSSQL::Utils.send(:unqualify_table_name, qtn),
46
+ "This qualifed_table_name #{qtn} did not unqualify correctly."
47
+ end
48
+ end
49
+
50
+ test 'return nil from Utils.unqualify_db_name when table_name is less than 2 qualified' do
51
+ @first_second_table_names.each do |qtn|
52
+ assert_equal nil, ArJdbc::MSSQL::Utils.send(:unqualify_db_name, qtn),
53
+ "This qualifed_table_name #{qtn} did not return nil."
54
+ end
55
+ end
56
+
57
+ test 'return clean db_name from Utils.unqualify_db_name when table is thrid level qualified' do
58
+ @third_table_names.each do |qtn|
59
+ assert_equal @expected_db_name,
60
+ ArJdbc::MSSQL::Utils.send(:unqualify_db_name, qtn),
61
+ "This qualifed_table_name #{qtn} did not unqualify the db_name correctly."
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ test "quote column name" do
68
+ connection = new_adapter_stub
69
+ assert_equal "[foo]", connection.quote_column_name("foo")
70
+ assert_equal "[bar]", connection.quote_column_name("[bar]")
71
+ assert_equal "[foo]]bar]", connection.quote_column_name("foo]bar")
72
+
73
+ assert_equal "[dbo].[foo]", connection.quote_column_name("dbo.foo")
74
+ assert_equal "[dbo].[bar]", connection.quote_column_name("[dbo].[bar]")
75
+ assert_equal "[foo].[bar]", connection.quote_column_name("[foo].bar")
76
+ assert_equal "[foo].[bar]", connection.quote_column_name("foo.[bar]")
77
+ end
78
+
79
+ private
80
+
81
+ def new_adapter_stub(config = {})
82
+ config = config.merge({
83
+ :adapter => 'jdbc',
84
+ :adapter_spec => ArJdbc::MSSQL,
85
+ :sqlserver_version => 2008
86
+ })
87
+ connection = stub('connection'); logger = nil
88
+ connection.stub_everything
89
+ adapter = ActiveRecord::ConnectionAdapters::JdbcAdapter.new connection, logger, config
90
+ yield(adapter) if block_given?
91
+ adapter
92
+ end
93
+
94
+ end
3
95
 
4
- # This tests ArJdbc::MsSQL#add_lock! without actually connecting to the database.
5
- class MssqlRowLockingSqlTest < Test::Unit::TestCase
96
+ # This tests ArJdbc::MSSQL#add_lock! without actually connecting to the database.
97
+ class MSSQLRowLockingSqlTest < Test::Unit::TestCase
6
98
 
7
99
  def test_find_all
8
100
  add_lock_test "Appointment.find(:all)",
@@ -136,22 +228,22 @@ class MssqlRowLockingSqlTest < Test::Unit::TestCase
136
228
  }
137
229
  end
138
230
 
231
+ class Dummy
232
+ include ::ArJdbc::MSSQL::LockHelpers::SqlServerAddLock
233
+ end
139
234
 
140
235
  private
141
236
 
142
- class Dummy
143
- include ::ArJdbc::MsSQL::LockHelpers::SqlServerAddLock
144
- end
145
-
146
- def add_lock!(sql, options={})
147
- result = sql.dup
148
- Dummy.new.add_lock!(result, {:lock=>true}.merge(options))
149
- result
150
- end
237
+ def add_lock!(sql, options={})
238
+ result = sql.dup
239
+ Dummy.new.add_lock!(result, {:lock=>true}.merge(options))
240
+ result
241
+ end
151
242
 
152
- def add_lock_test(message, before, after, options={})
153
- before = before.gsub(/\s*\n\s*/m, " ").strip
154
- after = after.gsub(/\s*\n\s*/m, " ").strip
155
- assert_equal after, add_lock!(before, options).strip, message
156
- end
243
+ def add_lock_test(message, before, after, options={})
244
+ before = before.gsub(/\s*\n\s*/m, " ").strip
245
+ after = after.gsub(/\s*\n\s*/m, " ").strip
246
+ assert_equal after, add_lock!(before, options).strip, message
247
+ end
248
+
157
249
  end
@@ -9,14 +9,12 @@ class MysqlDbCreateTest < Test::Unit::TestCase
9
9
  end
10
10
 
11
11
  def test_rake_db_create
12
+ omit_unless find_executable?("mysql")
12
13
  Rake::Task["db:create"].invoke
13
- if find_executable?("mysql")
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
14
+ with_mysql do |mysql|
15
+ mysql << "show databases where `Database` = '#{@db_name}';"
16
+ mysql.close_write
17
+ assert mysql.read =~ /#{@db_name}/m
20
18
  end
21
19
  end
22
20
 
@@ -24,4 +22,12 @@ class MysqlDbCreateTest < Test::Unit::TestCase
24
22
  Rake::Task["db:create"].invoke
25
23
  Rake::Task["db:test:purge"].invoke
26
24
  end
25
+
26
+ private
27
+
28
+ def with_mysql(args = nil)
29
+ exec = "mysql -u #{db_config[:username]} --password=#{db_config[:password]} #{args}"
30
+ IO.popen(exec, "r+") { |mysql| yield(mysql) }
31
+ end
32
+
27
33
  end
@@ -32,6 +32,24 @@ class OracleSimpleTest < Test::Unit::TestCase
32
32
  assert entries.first.login
33
33
  end
34
34
 
35
+ # @override
36
+ def test_exec_insert_bind_param_with_q_mark
37
+ sql = "INSERT INTO entries(id, title) VALUES (?, ?)"
38
+ connection.exec_insert sql, 'INSERT(with_q_mark)', [ [ nil, 1000 ], [ nil, "bar?!?" ] ]
39
+
40
+ entries = Entry.find_by_sql "SELECT * FROM entries WHERE title = 'bar?!?'"
41
+ assert entries.first
42
+ end
43
+
44
+ # @override
45
+ def test_raw_insert_bind_param_with_q_mark
46
+ sql = "INSERT INTO entries(id, title) VALUES (?, ?)"
47
+ name = "INSERT(raw_with_q_mark)"
48
+ pk = nil; id_value = 1001; sequence_name = nil
49
+ connection.insert sql, name, pk, id_value, sequence_name, [ [ nil, id_value ], [ nil, "?!huu!?" ] ]
50
+ assert Entry.exists?([ 'title LIKE ?', "%?!huu!?%" ])
51
+ end if Test::Unit::TestCase.ar_version('3.1') # no binds argument for <= 3.0
52
+
35
53
  include ExplainSupportTestMethods if ar_version("3.1")
36
54
 
37
55
  protected
@@ -1,4 +1,5 @@
1
1
  require 'abstract_db_create'
2
+ require 'db/postgres'
2
3
 
3
4
  class PostgresDbCreateTest < Test::Unit::TestCase
4
5
  include AbstractDbCreate
@@ -7,20 +8,18 @@ class PostgresDbCreateTest < Test::Unit::TestCase
7
8
  POSTGRES_CONFIG
8
9
  end
9
10
 
10
- if find_executable?("psql")
11
- def test_rake_db_create
12
- Rake::Task["db:create"].invoke
13
- output = `psql -d template1 -c '\\l'`
14
- assert output =~ /#{@db_name}/m
15
- end
11
+ PSQL_EXECUTABLE = find_executable?("psql")
12
+
13
+ def test_rake_db_create
14
+ omit_unless PSQL_EXECUTABLE
15
+ Rake::Task["db:create"].invoke
16
+ assert_match /#{@db_name}/m, psql("-d template1 -c '\\\l'")
17
+ end
16
18
 
17
- def test_rake_db_test_purge
18
- Rake::Task["db:create"].invoke
19
- Rake::Task["db:test:purge"].invoke
20
- end
21
- else
22
- def test_skipped
23
- end
19
+ def test_rake_db_test_purge
20
+ # omit_unless PSQL_EXECUTABLE
21
+ Rake::Task["db:create"].invoke
22
+ Rake::Task["db:test:purge"].invoke
24
23
  end
25
24
 
26
25
  def test_rake_db_create_does_not_load_full_environment
@@ -28,4 +27,18 @@ class PostgresDbCreateTest < Test::Unit::TestCase
28
27
  assert @rails_env_set
29
28
  assert !defined?(@full_environment_loaded) || !@full_environment_loaded
30
29
  end
30
+
31
+ private
32
+
33
+ def psql(args)
34
+ args = args.join(' ') unless args.is_a?(String)
35
+ if db_config[:host] != 'localhost'
36
+ args = "--host=#{db_config[:host]} #{args}"
37
+ end
38
+ if username = ENV['PSQL_USERNAME']
39
+ args = "--username=#{username} #{args}"
40
+ end
41
+ `psql #{args}`
42
+ end
43
+
31
44
  end
@@ -86,9 +86,38 @@ module ColumnNameQuotingTests
86
86
  end
87
87
 
88
88
  module DirtyAttributeTests
89
- def test_partial_update
90
- entry = Entry.new(:title => 'foo')
91
- old_updated_on = 1.hour.ago.beginning_of_day
89
+
90
+ def test_partial_update_with_updated_at
91
+ #ActiveRecord::Base.logger.level = Logger::DEBUG
92
+
93
+ user = User.create!(:login => 'cicina')
94
+ old_updated_at = 61.minutes.ago.in_time_zone
95
+
96
+ User.update_all({ :updated_at => old_updated_at }, :login => user.login)
97
+
98
+ with_partial_updates User, false do
99
+ assert_queries(1) { user.save! }
100
+ end
101
+
102
+ User.update_all({ :updated_at => old_updated_at }, :login => user.login)
103
+
104
+ with_partial_updates User, true do
105
+ assert_queries(0) { user.save! }
106
+ assert_datetime_equal old_updated_at, user.reload.updated_at
107
+
108
+ assert_queries(1) { user.login = 'cicinbrus'; user.save! }
109
+ assert_datetime_not_equal old_updated_at, user.reload.updated_at
110
+ end
111
+ ensure
112
+ #ActiveRecord::Base.logger.level = Logger::WARN
113
+ end
114
+
115
+ def test_partial_update_with_updated_on
116
+ #ActiveRecord::Base.logger.level = Logger::DEBUG
117
+ entry = Entry.create!(:title => 'foo')
118
+ old_updated_on = 25.hours.ago.beginning_of_day.in_time_zone
119
+
120
+ Entry.update_all({ :updated_on => old_updated_on }, :id => entry.id)
92
121
 
93
122
  with_partial_updates Entry, false do
94
123
  assert_queries(2) { 2.times { entry.save! } }
@@ -97,11 +126,13 @@ module DirtyAttributeTests
97
126
 
98
127
  with_partial_updates Entry, true do
99
128
  assert_queries(0) { 2.times { entry.save! } }
100
- assert_datetime_equal old_updated_on, entry.reload.updated_on
129
+ assert_date_equal old_updated_on, entry.reload.updated_on
101
130
 
102
131
  assert_queries(1) { entry.title = 'bar'; entry.save! }
103
- assert_not_equal old_updated_on, entry.reload.updated_on
132
+ assert_date_not_equal old_updated_on, entry.reload.updated_on
104
133
  end
134
+ ensure
135
+ #ActiveRecord::Base.logger.level = Logger::WARN
105
136
  end
106
137
 
107
138
  private
@@ -828,16 +859,15 @@ module ActiveRecord3TestMethods
828
859
  end
829
860
 
830
861
  module Tests
831
- if ActiveRecord::VERSION::MINOR == 2
832
- def test_visitor_accessor
833
- adapter = Entry.connection
834
- expected_visitors = adapter.config[:adapter_spec].
835
- arel2_visitors(adapter).values
836
- assert !adapter.visitor.nil?
837
- assert expected_visitors.include?(adapter.visitor.class)
838
- end
839
- end
840
-
862
+
863
+ def test_visitor_accessor
864
+ adapter = Entry.connection
865
+ adapter_spec = adapter.config[:adapter_spec]
866
+ expected_visitors = adapter_spec.arel2_visitors(adapter.config).values
867
+ assert_not_nil adapter.visitor
868
+ assert expected_visitors.include?(adapter.visitor.class)
869
+ end if Test::Unit::TestCase.ar_version('3.2') # >= 3.2
870
+
841
871
  def test_where
842
872
  entries = Entry.where(:title => @entry.title)
843
873
  assert_equal @entry, entries.first
@@ -0,0 +1,6 @@
1
+ require 'db/sqlite3'
2
+ require 'schema_dump'
3
+
4
+ class SQLite3SchemaDumpTest < Test::Unit::TestCase
5
+ include SchemaDumpTestMethods
6
+ end
@@ -9,38 +9,41 @@ class SQLite3TypeConversionTest < Test::Unit::TestCase
9
9
  else
10
10
  JInteger = Fixnum
11
11
  class Fixnum
12
- # Arbitrary value...we could pick
13
- MAX_VALUE = 2
12
+ MAX_VALUE = 1024 * 1024 # arbitrary value ... we could pick
14
13
  end
15
14
  end
16
15
 
17
- TEST_TIME = Time.at(1169964202)
18
- TEST_BINARY = "Some random binary data % \0 and then some"
19
-
20
16
  def self.startup; DbTypeMigration.up; end
21
17
  def self.shutdown; DbTypeMigration.down; end
22
18
 
23
- def setup
24
- super
19
+ TEST_BINARY = "Some random binary data % \0 and then some"
20
+
21
+ @@time_zone = Time.zone
22
+
23
+ setup do
24
+ Time.zone = ActiveSupport::TimeZone['UTC']
25
25
  DbType.delete_all
26
- DbType.create(
27
- :sample_timestamp => TEST_TIME,
28
- :sample_datetime => TEST_TIME,
29
- :sample_time => TEST_TIME,
30
- :sample_date => TEST_TIME,
26
+ some_time = Time.now
27
+ DbType.create!(
28
+ :sample_timestamp => some_time,
29
+ :sample_datetime => some_time.to_datetime,
30
+ :sample_time => some_time.to_time,
31
+ :sample_date => some_time.to_date,
31
32
  :sample_decimal => JInteger::MAX_VALUE + 1,
32
33
  :sample_small_decimal => 3.14,
33
34
  :sample_binary => TEST_BINARY)
34
- DbType.create(
35
- :sample_timestamp => TEST_TIME,
36
- :sample_datetime => TEST_TIME,
37
- :sample_time => TEST_TIME,
38
- :sample_date => TEST_TIME,
35
+ DbType.create!(
36
+ :sample_timestamp => some_time,
37
+ :sample_datetime => some_time.to_datetime,
38
+ :sample_time => some_time.to_time,
39
+ :sample_date => some_time.to_date,
39
40
  :sample_decimal => JInteger::MAX_VALUE + 1,
40
41
  :sample_small_decimal => 1.0,
41
42
  :sample_binary => TEST_BINARY)
42
43
  end
43
44
 
45
+ teardown { Time.zone = @@time_zone; DbType.delete_all }
46
+
44
47
  def test_decimal
45
48
  types = DbType.first
46
49
  assert_equal((JInteger::MAX_VALUE + 1), types.sample_decimal)
@@ -135,11 +135,53 @@ class Test::Unit::TestCase
135
135
  #assert_equal e_usec, a_usec, "<#{expected}> but was <#{actual}> (differ at :usec / 1000)"
136
136
  end
137
137
 
138
+ def assert_date_not_equal expected, actual
139
+ actual = actual_in_expected_time_zone(expected, actual)
140
+ actual = actual.to_date if actual.is_a?(Time)
141
+ assert_not_equal(expected.nil? ? nil : expected.to_date, actual)
142
+ end
143
+
144
+ def assert_time_not_equal expected, actual, msg = nil
145
+ actual = actual_in_expected_time_zone(expected, actual)
146
+ equal = true
147
+ [ :hour, :min, :sec ].each do |method|
148
+ equal &&= ( expected.send(method) == actual.send(method) )
149
+ end
150
+ assert ! equal, msg || "<#{expected}> to not (time) equal to <#{actual}> but did"
151
+ end
152
+
153
+ def assert_datetime_not_equal expected, actual
154
+ if date_equal?(expected, actual) && time_equal?(expected, actual)
155
+ assert false, "<#{expected}> to not (datetime) equal to <#{actual}> but did"
156
+ end
157
+ end
158
+
138
159
  private
139
160
 
161
+ def date_equal?(expected, actual)
162
+ actual = actual_in_expected_time_zone(expected, actual)
163
+ actual = actual.to_date if actual.is_a?(Time)
164
+ (expected.nil? ? nil : expected.to_date) == actual
165
+ end
166
+
167
+ def time_equal?(expected, actual)
168
+ actual = actual_in_expected_time_zone(expected, actual)
169
+ equal = true; [ :hour, :min, :sec ].each do |method|
170
+ equal &&= ( expected.send(method) == actual.send(method) )
171
+ end
172
+ equal
173
+ end
174
+
140
175
  def actual_in_expected_time_zone(expected, actual)
141
- if actual.is_a?(Time) && expected.respond_to?(:time_zone)
142
- return actual.in_time_zone expected.time_zone
176
+ if actual.respond_to?(:in_time_zone)
177
+ if expected.respond_to?(:time_zone)
178
+ return actual.in_time_zone expected.time_zone
179
+ end
180
+ if expected.is_a?(Time) # due AR 2.3
181
+ #expected = expected.in_time_zone
182
+ #return actual.in_time_zone expected.time_zone
183
+ return actual.in_time_zone ActiveSupport::TimeZone[expected.zone]
184
+ end
143
185
  end
144
186
  actual
145
187
  end