activerecord-jdbc-adapter 1.2.8 → 1.2.9

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