activerecord-oracle_enhanced-adapter 7.0.0 → 7.1.0

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +56 -0
  3. data/README.md +0 -1
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +5 -0
  6. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +1 -1
  7. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +2 -2
  8. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +35 -27
  9. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +15 -2
  10. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +9 -2
  11. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +3 -3
  12. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +24 -15
  13. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +3 -3
  14. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +7 -5
  15. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +1 -1
  16. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +5 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +1 -1
  18. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +24 -22
  19. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +17 -17
  20. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +72 -29
  21. data/lib/activerecord-oracle_enhanced-adapter.rb +8 -0
  22. data/lib/arel/visitors/oracle.rb +6 -3
  23. data/lib/arel/visitors/oracle12.rb +6 -5
  24. data/lib/arel/visitors/oracle_common.rb +46 -0
  25. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +24 -5
  26. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +7 -2
  27. data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +2 -2
  28. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +3 -0
  29. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +25 -15
  30. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +15 -18
  31. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +14 -10
  32. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +2 -2
  33. data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +24 -0
  34. data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
  35. data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +4 -2
  36. data/spec/active_record/oracle_enhanced/type/integer_spec.rb +8 -0
  37. data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +3 -3
  38. data/spec/active_record/oracle_enhanced/type/raw_spec.rb +15 -0
  39. data/spec/active_record/oracle_enhanced/type/text_spec.rb +18 -3
  40. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +5 -1
  41. data/spec/spec_config.yaml.template +2 -2
  42. data/spec/spec_helper.rb +14 -3
  43. metadata +27 -9
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "oracle_common"
4
+
3
5
  module Arel # :nodoc: all
4
6
  module Visitors
5
7
  class Oracle12 < Arel::Visitors::ToSql
8
+ include OracleCommon
9
+
6
10
  private
7
11
  def visit_Arel_Nodes_SelectStatement(o, collector)
8
12
  # Oracle does not allow LIMIT clause with select for update
@@ -45,7 +49,6 @@ module Arel # :nodoc: all
45
49
  def visit_Arel_Nodes_HomogeneousIn(o, collector)
46
50
  in_clause_length = @connection.in_clause_length
47
51
  values = o.casted_values.map { |v| @connection.quote(v) }
48
- column_name = quote_table_name(o.table_name) + "." + quote_column_name(o.column_name)
49
52
  operator =
50
53
  if o.type == :in
51
54
  " IN ("
@@ -54,7 +57,7 @@ module Arel # :nodoc: all
54
57
  end
55
58
 
56
59
  if !Array === values || values.length <= in_clause_length
57
- collector << column_name
60
+ visit o.left, collector
58
61
  collector << operator
59
62
 
60
63
  expr =
@@ -76,15 +79,13 @@ module Arel # :nodoc: all
76
79
  collector << "("
77
80
  values.each_slice(in_clause_length).each_with_index do |valuez, i|
78
81
  collector << separator unless i == 0
79
- collector << column_name
82
+ visit o.left, collector
80
83
  collector << operator
81
84
  collector << valuez.join(",")
82
85
  collector << ")"
83
86
  end
84
87
  collector << ")"
85
88
  end
86
-
87
- collector
88
89
  end
89
90
 
90
91
  def visit_Arel_Nodes_UpdateStatement(o, collector)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ module Visitors
5
+ module OracleCommon
6
+ private
7
+ # Oracle can't compare CLOB columns with standard SQL operators for comparison.
8
+ # We need to replace standard equality for text/binary columns to use DBMS_LOB.COMPARE function.
9
+ # Fixes ORA-00932: inconsistent datatypes: expected - got CLOB
10
+ def visit_Arel_Nodes_Equality(o, collector)
11
+ left = o.left
12
+ return super unless %i(text binary).include?(cached_column_for(left)&.type)
13
+
14
+ # https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lob.htm#i1016668
15
+ # returns 0 when the comparison succeeds
16
+ comparator = Arel::Nodes::NamedFunction.new("DBMS_LOB.COMPARE", [left, o.right])
17
+ collector = visit comparator, collector
18
+ collector << " = 0"
19
+ collector
20
+ end
21
+
22
+ def visit_Arel_Nodes_Matches(o, collector)
23
+ if !o.case_sensitive && o.left && o.right
24
+ o.left = Arel::Nodes::NamedFunction.new("UPPER", [o.left])
25
+ o.right = Arel::Nodes::NamedFunction.new("UPPER", [o.right])
26
+ end
27
+
28
+ super o, collector
29
+ end
30
+
31
+ def cached_column_for(attr)
32
+ return unless Arel::Attributes::Attribute === attr
33
+
34
+ table = attr.relation.name
35
+ return unless schema_cache.columns_hash?(table)
36
+
37
+ column = attr.name.to_s
38
+ schema_cache.columns_hash(table)[column]
39
+ end
40
+
41
+ def schema_cache
42
+ @connection.schema_cache
43
+ end
44
+ end
45
+ end
46
+ end
@@ -44,7 +44,7 @@ describe "OracleEnhancedAdapter establish connection" do
44
44
  it "should not use JDBC statement caching" do
45
45
  if ORACLE_ENHANCED_CONNECTION == :jdbc
46
46
  ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS)
47
- expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to eq(false)
47
+ expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to be(false)
48
48
  expect(ActiveRecord::Base.connection.raw_connection.getStatementCacheSize).to eq(-1)
49
49
  end
50
50
  end
@@ -52,12 +52,26 @@ describe "OracleEnhancedAdapter establish connection" do
52
52
  it "should use JDBC statement caching" do
53
53
  if ORACLE_ENHANCED_CONNECTION == :jdbc
54
54
  ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_statement_cache_size: 100))
55
- expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to eq(true)
55
+ expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to be(true)
56
56
  expect(ActiveRecord::Base.connection.raw_connection.getStatementCacheSize).to eq(100)
57
57
  # else: don't raise error if OCI connection has parameter "jdbc_statement_cache_size", still ignore it
58
58
  end
59
59
  end
60
60
 
61
+ it "should not encrypt JDBC network connection" do
62
+ if ORACLE_ENHANCED_CONNECTION == :jdbc
63
+ @conn = ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_connect_properties: { "oracle.net.encryption_client" => "REJECTED" }))
64
+ expect(@conn.select("SELECT COUNT(*) Records FROM v$Session_Connect_Info WHERE SID=SYS_CONTEXT('USERENV', 'SID') AND Network_Service_Banner LIKE '%Encryption service adapter%'")).to eq([{ "records" => 0 }])
65
+ end
66
+ end
67
+
68
+ it "should encrypt JDBC network connection" do
69
+ if ORACLE_ENHANCED_CONNECTION == :jdbc
70
+ @conn = ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_connect_properties: { "oracle.net.encryption_client" => "REQUESTED" }))
71
+ expect(@conn.select("SELECT COUNT(*) Records FROM v$Session_Connect_Info WHERE SID=SYS_CONTEXT('USERENV', 'SID') AND Network_Service_Banner LIKE '%Encryption service adapter%'")).to eq([{ "records" => 1 }])
72
+ end
73
+ end
74
+
61
75
  it "should connect to database using service_name" do
62
76
  ActiveRecord::Base.establish_connection(SERVICE_NAME_CONNECTION_PARAMS)
63
77
  expect(ActiveRecord::Base.connection).not_to be_nil
@@ -227,7 +241,7 @@ describe "OracleEnhancedConnection" do
227
241
  end
228
242
 
229
243
  after(:all) do
230
- Object.send(:remove_const, "Post")
244
+ Object.send(:remove_const, "Post") if defined?(Post)
231
245
  ActiveRecord::Base.clear_cache!
232
246
  end
233
247
 
@@ -392,7 +406,7 @@ describe "OracleEnhancedConnection" do
392
406
  @conn.exec "DROP TABLE test_employees" rescue nil
393
407
  end
394
408
 
395
- it "should execute prepared statement with decimal bind parameter " do
409
+ it "should execute prepared statement with decimal bind parameter" do
396
410
  cursor = @conn.prepare("INSERT INTO test_employees VALUES(:1)")
397
411
  type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "NUMBER", type: :decimal, limit: 10, precision: nil, scale: 2)
398
412
  column = ActiveRecord::ConnectionAdapters::OracleEnhanced::Column.new("age", nil, type_metadata, false, comment: nil)
@@ -414,7 +428,7 @@ describe "OracleEnhancedConnection" do
414
428
 
415
429
  before(:all) do
416
430
  ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
417
- @conn = ActiveRecord::Base.connection.instance_variable_get("@connection")
431
+ @conn = ActiveRecord::Base.connection.send(:_connection)
418
432
  @sys_conn = ActiveRecord::ConnectionAdapters::OracleEnhanced::Connection.create(SYS_CONNECTION_PARAMS)
419
433
  schema_define do
420
434
  create_table :posts, force: true
@@ -447,6 +461,11 @@ describe "OracleEnhancedConnection" do
447
461
  expect(@conn.exec("SELECT * FROM dual")).not_to be_nil
448
462
  end
449
463
 
464
+ it "should reconnect and execute SQL statement if connection is lost and allow_retry is passed" do
465
+ kill_current_session
466
+ expect(@conn.exec("SELECT * FROM dual", allow_retry: true)).not_to be_nil
467
+ end
468
+
450
469
  it "should not reconnect and execute SQL statement if connection is lost and auto retry is disabled" do
451
470
  # @conn.auto_retry = false
452
471
  ActiveRecord::Base.connection.auto_retry = false
@@ -16,6 +16,7 @@ describe "Oracle Enhanced adapter database tasks" do
16
16
  ActiveRecord::Tasks::DatabaseTasks.create(new_user_config)
17
17
  end
18
18
  end
19
+
19
20
  it "creates user" do
20
21
  query = "SELECT COUNT(*) FROM dba_users WHERE UPPER(username) = '#{new_user_config[:username].upcase}'"
21
22
  expect(ActiveRecord::Base.connection.select_value(query)).to eq(1)
@@ -62,6 +63,7 @@ describe "Oracle Enhanced adapter database tasks" do
62
63
 
63
64
  describe "drop" do
64
65
  before { ActiveRecord::Tasks::DatabaseTasks.drop(config) }
66
+
65
67
  it "drops all tables" do
66
68
  expect(ActiveRecord::Base.connection.table_exists?(:test_posts)).to be_falsey
67
69
  end
@@ -69,6 +71,7 @@ describe "Oracle Enhanced adapter database tasks" do
69
71
 
70
72
  describe "purge" do
71
73
  before { ActiveRecord::Tasks::DatabaseTasks.purge(config) }
74
+
72
75
  it "drops all tables" do
73
76
  expect(ActiveRecord::Base.connection.table_exists?(:test_posts)).to be_falsey
74
77
  expect(ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM RECYCLEBIN")).to eq(0)
@@ -78,12 +81,13 @@ describe "Oracle Enhanced adapter database tasks" do
78
81
  describe "structure" do
79
82
  let(:temp_file) { Tempfile.create(["oracle_enhanced", ".sql"]).path }
80
83
  before do
81
- ActiveRecord::SchemaMigration.create_table
84
+ ActiveRecord::Base.connection.schema_migration.create_table
82
85
  ActiveRecord::Base.connection.execute "INSERT INTO schema_migrations (version) VALUES ('20150101010000')"
83
86
  end
84
87
 
85
88
  describe "structure_dump" do
86
89
  before { ActiveRecord::Tasks::DatabaseTasks.structure_dump(config, temp_file) }
90
+
87
91
  it "dumps the database structure to a file without the schema information" do
88
92
  contents = File.read(temp_file)
89
93
  expect(contents).to include('CREATE TABLE "TEST_POSTS"')
@@ -97,6 +101,7 @@ describe "Oracle Enhanced adapter database tasks" do
97
101
  ActiveRecord::Tasks::DatabaseTasks.drop(config)
98
102
  ActiveRecord::Tasks::DatabaseTasks.structure_load(config, temp_file)
99
103
  end
104
+
100
105
  it "loads the database structure from a file" do
101
106
  expect(ActiveRecord::Base.connection.table_exists?(:test_posts)).to be_truthy
102
107
  end
@@ -104,7 +109,7 @@ describe "Oracle Enhanced adapter database tasks" do
104
109
 
105
110
  after do
106
111
  File.unlink(temp_file)
107
- ActiveRecord::SchemaMigration.drop_table
112
+ ActiveRecord::Base.connection.schema_migration.drop_table
108
113
  end
109
114
  end
110
115
 
@@ -47,7 +47,7 @@ describe "OracleEnhancedAdapter logging dbms_output from plsql" do
47
47
  expect(@logger.output(:debug)).not_to match(/^DBMS_OUTPUT/)
48
48
  end
49
49
 
50
- it "should log dbms output lines to the rails log" do
50
+ it "should log dbms output longer lines to the rails log" do
51
51
  @conn.enable_dbms_output
52
52
 
53
53
  expect(@conn.select_all("select more_than_five_characters_long('hi there') is_it_long from dual").to_a).to eq([{ "is_it_long" => 1 }])
@@ -57,7 +57,7 @@ describe "OracleEnhancedAdapter logging dbms_output from plsql" do
57
57
  expect(@logger.output(:debug)).to match(/^DBMS_OUTPUT: about to return: 1$/)
58
58
  end
59
59
 
60
- it "should log dbms output lines to the rails log" do
60
+ it "should log dbms output shorter lines to the rails log" do
61
61
  @conn.enable_dbms_output
62
62
 
63
63
  expect(@conn.select_all("select more_than_five_characters_long('short') is_it_long from dual").to_a).to eq([{ "is_it_long" => 0 }])
@@ -127,6 +127,7 @@ describe "OracleEnhancedAdapter schema dump" do
127
127
  remove_foreign_key :test_comments, name: "comments_posts_baz_fooz_fk" rescue nil
128
128
  end
129
129
  end
130
+
130
131
  after(:all) do
131
132
  schema_define do
132
133
  drop_table :test_comments, if_exists: true
@@ -383,6 +384,7 @@ describe "OracleEnhancedAdapter schema dump" do
383
384
  end
384
385
  end
385
386
  end
387
+
386
388
  after(:all) do
387
389
  if @oracle11g_or_higher
388
390
  schema_define do
@@ -390,6 +392,7 @@ describe "OracleEnhancedAdapter schema dump" do
390
392
  end
391
393
  end
392
394
  end
395
+
393
396
  it "should dump correctly" do
394
397
  output = dump_table_schema "test_names"
395
398
  expect(output).not_to match(/t\.index .+FIRST_NAME.+$/)
@@ -550,6 +550,7 @@ end
550
550
  class ::TestPost < ActiveRecord::Base
551
551
  end
552
552
  end
553
+
553
554
  it "should use default tablespace for clobs" do
554
555
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = DATABASE_NON_DEFAULT_TABLESPACE
555
556
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = nil
@@ -880,7 +881,7 @@ end
880
881
  expect(TestPost.columns_hash["a" * 128]).not_to be_nil
881
882
  end
882
883
 
883
- it "should add lob column with non_default tablespace" do
884
+ it "should add text type lob column with non_default tablespace" do
884
885
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = DATABASE_NON_DEFAULT_TABLESPACE
885
886
  schema_define do
886
887
  add_column :test_posts, :body, :text
@@ -888,7 +889,7 @@ end
888
889
  expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'BODY'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
889
890
  end
890
891
 
891
- it "should add lob column with non_default tablespace" do
892
+ it "should add ntext type lob column with non_default tablespace" do
892
893
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = DATABASE_NON_DEFAULT_TABLESPACE
893
894
  schema_define do
894
895
  add_column :test_posts, :body, :ntext
@@ -995,12 +996,12 @@ end
995
996
 
996
997
  it "should include virtual columns and not try to update them" do
997
998
  tf = TestFraction.columns.detect { |c| c.virtual? }
998
- expect(tf).not_to be nil
999
+ expect(tf).not_to be_nil
999
1000
  expect(tf.name).to eq("percent")
1000
1001
  expect(tf.virtual?).to be true
1001
1002
  expect do
1002
1003
  tf = TestFraction.new(numerator: 20, denominator: 100)
1003
- expect(tf.percent).to be nil # not whatever is in DATA_DEFAULT column
1004
+ expect(tf.percent).to be_nil # not whatever is in DATA_DEFAULT column
1004
1005
  tf.save!
1005
1006
  tf.reload
1006
1007
  end.not_to raise_error
@@ -1013,11 +1014,11 @@ end
1013
1014
  end
1014
1015
  TestFraction.reset_column_information
1015
1016
  tf = TestFraction.columns.detect { |c| c.name == "rem" }
1016
- expect(tf).not_to be nil
1017
+ expect(tf).not_to be_nil
1017
1018
  expect(tf.virtual?).to be true
1018
1019
  expect do
1019
1020
  tf = TestFraction.new(numerator: 7, denominator: 5)
1020
- expect(tf.rem).to be nil
1021
+ expect(tf.rem).to be_nil
1021
1022
  tf.save!
1022
1023
  tf.reload
1023
1024
  end.not_to raise_error
@@ -1030,13 +1031,13 @@ end
1030
1031
  end
1031
1032
  TestFraction.reset_column_information
1032
1033
  tf = TestFraction.columns.detect { |c| c.name == "expression" }
1033
- expect(tf).not_to be nil
1034
+ expect(tf).not_to be_nil
1034
1035
  expect(tf.virtual?).to be true
1035
1036
  expect(tf.type).to be :string
1036
1037
  expect(tf.limit).to be 100
1037
1038
  expect do
1038
1039
  tf = TestFraction.new(numerator: 7, denominator: 5)
1039
- expect(tf.expression).to be nil
1040
+ expect(tf.expression).to be_nil
1040
1041
  tf.save!
1041
1042
  tf.reload
1042
1043
  end.not_to raise_error
@@ -1050,14 +1051,14 @@ end
1050
1051
  end
1051
1052
  TestFraction.reset_column_information
1052
1053
  tf = TestFraction.columns.detect { |c| c.name == "percent" }
1053
- expect(tf).not_to be nil
1054
+ expect(tf).not_to be_nil
1054
1055
  expect(tf.virtual?).to be true
1055
1056
  expect(tf.type).to be :decimal
1056
1057
  expect(tf.precision).to be 15
1057
1058
  expect(tf.scale).to be 2
1058
1059
  expect do
1059
1060
  tf = TestFraction.new(numerator: 11, denominator: 17)
1060
- expect(tf.percent).to be nil
1061
+ expect(tf.percent).to be_nil
1061
1062
  tf.save!
1062
1063
  tf.reload
1063
1064
  end.not_to raise_error
@@ -1070,14 +1071,14 @@ end
1070
1071
  end
1071
1072
  TestFraction.reset_column_information
1072
1073
  tf = TestFraction.columns.detect { |c| c.name == "percent" }
1073
- expect(tf).not_to be nil
1074
+ expect(tf).not_to be_nil
1074
1075
  expect(tf.virtual?).to be true
1075
1076
  expect(tf.type).to be :decimal
1076
1077
  expect(tf.precision).to be 12
1077
1078
  expect(tf.scale).to be 5
1078
1079
  expect do
1079
1080
  tf = TestFraction.new(numerator: 11, denominator: 17)
1080
- expect(tf.percent).to be nil
1081
+ expect(tf.percent).to be_nil
1081
1082
  tf.save!
1082
1083
  tf.reload
1083
1084
  end.not_to raise_error
@@ -1157,6 +1158,7 @@ end
1157
1158
  @conn.drop_table :tablespace_tests, if_exists: true
1158
1159
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:table)
1159
1160
  end
1161
+
1160
1162
  it "should use correct tablespace" do
1161
1163
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:table] = DATABASE_NON_DEFAULT_TABLESPACE
1162
1164
  @conn.create_table :tablespace_tests do |t|
@@ -1171,6 +1173,7 @@ end
1171
1173
  @conn.drop_table :tablespace_tests, if_exists: true
1172
1174
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:table)
1173
1175
  end
1176
+
1174
1177
  it "should use correct tablespace" do
1175
1178
  @conn.create_table :tablespace_tests, id: false, organization: "INDEX INITRANS 4 COMPRESS 1", tablespace: "bogus" do |t|
1176
1179
  t.integer :id
@@ -1206,7 +1209,14 @@ end
1206
1209
  schema_define do
1207
1210
  add_index :keyboards, "lower(name)", unique: true, name: :index_keyboards_on_lower_name
1208
1211
  end
1209
- expect(@would_execute_sql).not_to match(/ALTER +TABLE .* ADD CONSTRAINT .* UNIQUE \(.*\(.*\)\)/)
1212
+ expect(@would_execute_sql).not_to include("ADD CONSTRAINT")
1213
+ end
1214
+
1215
+ it "should add unique constraint only to the index where it was defined" do
1216
+ schema_define do
1217
+ add_index :keyboards, ["name"], unique: true, name: :this_index
1218
+ end
1219
+ expect(@would_execute_sql.lines.last).to match(/ALTER +TABLE .* ADD CONSTRAINT .* UNIQUE \(.*\) USING INDEX "THIS_INDEX";/)
1210
1220
  end
1211
1221
  end
1212
1222
 
@@ -1218,7 +1228,7 @@ end
1218
1228
  before do
1219
1229
  @conn = ActiveRecord::Base.connection
1220
1230
 
1221
- ActiveRecord::SchemaMigration.create_table
1231
+ ActiveRecord::Base.connection.schema_migration.create_table
1222
1232
  end
1223
1233
 
1224
1234
  context "multi insert is supported" do
@@ -1246,7 +1256,7 @@ end
1246
1256
  end
1247
1257
 
1248
1258
  after do
1249
- ActiveRecord::SchemaMigration.drop_table
1259
+ ActiveRecord::Base.connection.schema_migration.drop_table
1250
1260
  end
1251
1261
  end
1252
1262
  end
@@ -9,6 +9,7 @@ describe "OracleEnhancedAdapter structure dump" do
9
9
  @oracle11g_or_higher = !! @conn.select_value(
10
10
  "select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) >= 11")
11
11
  end
12
+
12
13
  describe "structure dump" do
13
14
  before(:each) do
14
15
  @conn.create_table :test_posts, force: true do |t|
@@ -228,25 +229,13 @@ describe "OracleEnhancedAdapter structure dump" do
228
229
  dump = ActiveRecord::Base.connection.structure_dump
229
230
  expect(dump).to match(/#{comment_sql}/)
230
231
  end
231
-
232
- it "should dump table comments" do
233
- comment_sql = %Q(COMMENT ON TABLE "TEST_POSTS" IS 'Test posts with ''some'' "quotes"')
234
- @conn.execute comment_sql
235
- dump = ActiveRecord::Base.connection.structure_dump
236
- expect(dump).to match(/#{comment_sql}/)
237
- end
238
-
239
- it "should dump column comments" do
240
- comment_sql = %Q(COMMENT ON COLUMN "TEST_POSTS"."TITLE" IS 'The title of the post with ''some'' "quotes"')
241
- @conn.execute comment_sql
242
- dump = ActiveRecord::Base.connection.structure_dump
243
- expect(dump).to match(/#{comment_sql}/)
244
- end
245
232
  end
233
+
246
234
  describe "temporary tables" do
247
235
  after(:all) do
248
236
  @conn.drop_table :test_comments, if_exists: true
249
237
  end
238
+
250
239
  it "should dump correctly" do
251
240
  @conn.create_table :test_comments, temporary: true, id: false do |t|
252
241
  t.integer :post_id
@@ -261,26 +250,32 @@ describe "OracleEnhancedAdapter structure dump" do
261
250
  before(:each) do
262
251
  @conn.execute sql
263
252
  end
253
+
264
254
  after(:each) do
265
255
  @conn.execute "drop SEQUENCE \"#{sequence_name}\""
266
256
  end
257
+
267
258
  subject do
268
259
  ActiveRecord::Base.connection.structure_dump
269
260
  end
261
+
270
262
  context "default sequence" do
271
263
  let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\"" }
272
264
  it { is_expected.to_not match(%r{CREATE SEQUENCE "#{sequence_name}" MAXVALUE \d+ MINVALUE \d+ NOORDER NOCYCLE}) }
273
265
  end
266
+
274
267
  context "noorder" do
275
268
  let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" NOORDER" }
276
269
  it { is_expected.to include("NOORDER") }
277
270
  it { is_expected.to_not include(" ORDER") }
278
271
  end
272
+
279
273
  context "order" do
280
274
  let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" ORDER" }
281
275
  it { is_expected.to include(" ORDER") }
282
276
  it { is_expected.to_not include("NOORDER") }
283
277
  end
278
+
284
279
  context "min max values" do
285
280
  let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" MINVALUE 7 MAXVALUE 444" }
286
281
  it { is_expected.to include("MINVALUE 7") }
@@ -317,6 +312,7 @@ describe "OracleEnhancedAdapter structure dump" do
317
312
  t.string :foo
318
313
  end
319
314
  end
315
+
320
316
  it "should dump drop sql for just temp tables" do
321
317
  dump = @conn.temp_table_drop
322
318
  expect(dump).to match(/DROP TABLE "TEMP_TBL"/)
@@ -338,10 +334,9 @@ describe "OracleEnhancedAdapter structure dump" do
338
334
  let(:dump) { ActiveRecord::Base.connection.dump_schema_information }
339
335
 
340
336
  before do
341
- ActiveRecord::SchemaMigration.reset_table_name
342
- ActiveRecord::SchemaMigration.create_table
337
+ ActiveRecord::Base.connection.schema_migration.create_table
343
338
  versions.each do |i|
344
- ActiveRecord::SchemaMigration.create!(version: i)
339
+ ActiveRecord::Base.connection.schema_migration.create_version(i)
345
340
  end
346
341
  end
347
342
 
@@ -381,7 +376,7 @@ describe "OracleEnhancedAdapter structure dump" do
381
376
  end
382
377
 
383
378
  after do
384
- ActiveRecord::SchemaMigration.drop_table
379
+ ActiveRecord::Base.connection.schema_migration.drop_table
385
380
  end
386
381
  end
387
382
 
@@ -444,6 +439,7 @@ describe "OracleEnhancedAdapter structure dump" do
444
439
  create or replace type full_drop_test_type as table of number
445
440
  SQL
446
441
  end
442
+
447
443
  after(:each) do
448
444
  @conn.drop_table :full_drop_test
449
445
  @conn.drop_table :full_drop_test_temp
@@ -455,6 +451,7 @@ describe "OracleEnhancedAdapter structure dump" do
455
451
  @conn.execute "DROP PROCEDURE FULL_DROP_TEST_PROCEDURE" rescue nil
456
452
  @conn.execute "DROP TYPE FULL_DROP_TEST_TYPE" rescue nil
457
453
  end
454
+
458
455
  it "should contain correct sql" do
459
456
  drop = @conn.full_drop
460
457
  expect(drop).to match(/DROP TABLE "FULL_DROP_TEST" CASCADE CONSTRAINTS/)
@@ -83,7 +83,7 @@ describe "OracleEnhancedAdapter" do
83
83
  expect(@logger.logged(:debug).last).to match(/select .* from all_constraints/im)
84
84
  end
85
85
 
86
- it "should get primary key from database at first time" do
86
+ it "should get primary key from database at second time without query" do
87
87
  expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
88
88
  @logger.clear(:debug)
89
89
  expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
@@ -129,6 +129,7 @@ describe "OracleEnhancedAdapter" do
129
129
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = "UNUSED"
130
130
  @conn = ActiveRecord::Base.connection
131
131
  end
132
+
132
133
  after(:all) do
133
134
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces = {}
134
135
  end
@@ -136,6 +137,7 @@ describe "OracleEnhancedAdapter" do
136
137
  after(:each) do
137
138
  @conn.drop_table :foos, if_exists: true
138
139
  end
140
+
139
141
  it "should create ok" do
140
142
  @conn.create_table :foos, temporary: true, id: false do |t|
141
143
  t.integer :id
@@ -441,7 +443,7 @@ describe "OracleEnhancedAdapter" do
441
443
  end
442
444
  end
443
445
  class ::TestSerializedColumn < ActiveRecord::Base
444
- serialize :serialized, Array
446
+ serialize :serialized, type: Array
445
447
  end
446
448
  end
447
449
 
@@ -470,12 +472,12 @@ describe "OracleEnhancedAdapter" do
470
472
  serialized_column.serialized << new_value
471
473
  expect(serialized_column.serialized).to eq([new_value])
472
474
  serialized_column.save
473
- expect(serialized_column.save!).to eq(true)
475
+ expect(serialized_column.save!).to be(true)
474
476
 
475
477
  serialized_column.reload
476
478
  expect(serialized_column.serialized).to eq([new_value])
477
479
  serialized_column.serialized = []
478
- expect(serialized_column.save!).to eq(true)
480
+ expect(serialized_column.save!).to be(true)
479
481
  end
480
482
  end
481
483
 
@@ -514,7 +516,7 @@ describe "OracleEnhancedAdapter" do
514
516
  binary_column_object = TestBinaryColumn.new
515
517
  binary_column_object.attachment = binary_value
516
518
 
517
- expect(binary_column_object.save!).to eq(true)
519
+ expect(binary_column_object.save!).to be(true)
518
520
  end
519
521
  end
520
522
 
@@ -622,8 +624,8 @@ describe "OracleEnhancedAdapter" do
622
624
  end
623
625
 
624
626
  it "should test table existence" do
625
- expect(@conn.table_exists?("TEST_POSTS")).to eq true
626
- expect(@conn.table_exists?("NOT_EXISTING")).to eq false
627
+ expect(@conn.table_exists?("TEST_POSTS")).to be true
628
+ expect(@conn.table_exists?("NOT_EXISTING")).to be false
627
629
  end
628
630
 
629
631
  it "should return array from indexes with bind usage" do
@@ -648,13 +650,13 @@ describe "OracleEnhancedAdapter" do
648
650
  expect(@logger.logged(:debug).last).to match(/\["table_name", "TEST_POSTS"\]/)
649
651
  end
650
652
 
651
- it "should not raise missing IN/OUT parameter like issue 1687 " do
653
+ it "should not raise missing IN/OUT parameter like issue 1678" do
652
654
  # "to_sql" enforces unprepared_statement including dictionary access SQLs
653
655
  expect { User.joins(:group).to_sql }.not_to raise_exception
654
656
  end
655
657
 
656
658
  it "should return false from temporary_table? with bind usage" do
657
- expect(@conn.temporary_table?("TEST_POSTS")).to eq false
659
+ expect(@conn.temporary_table?("TEST_POSTS")).to be false
658
660
  expect(@logger.logged(:debug).last).to match(/:table_name/)
659
661
  expect(@logger.logged(:debug).last).to match(/\["table_name", "TEST_POSTS"\]/)
660
662
  end
@@ -721,12 +723,14 @@ describe "OracleEnhancedAdapter" do
721
723
  end
722
724
  end
723
725
  end
726
+
724
727
  after(:all) do
725
728
  schema_define do
726
729
  drop_table :table_with_name_thats_just_ok,
727
730
  sequence_name: "suitably_short_seq" rescue nil
728
731
  end
729
732
  end
733
+
730
734
  it "should create table with custom sequence name" do
731
735
  expect(@conn.select_value("select suitably_short_seq.nextval from dual")).to eq(1)
732
736
  end
@@ -767,7 +771,7 @@ describe "OracleEnhancedAdapter" do
767
771
  expect(post.explain).to include("| TABLE ACCESS FULL| TEST_POSTS |")
768
772
  end
769
773
 
770
- it "should explain considers hints with /*+ */ " do
774
+ it "should explain considers hints with /*+ */" do
771
775
  post = TestPost.optimizer_hints("/*+ FULL (\"TEST_POSTS\") */")
772
776
  post = post.where(id: 1)
773
777
  expect(post.explain).to include("| TABLE ACCESS FULL| TEST_POSTS |")
@@ -151,10 +151,10 @@ describe "OracleEnhancedAdapter boolean type detection based on string column ty
151
151
  expect(@employee3.test_boolean_before_type_cast).to eq("N")
152
152
  create_employee3(test_boolean: nil)
153
153
  expect(@employee3.test_boolean.class).to eq(NilClass)
154
- expect(@employee3.test_boolean_before_type_cast).to eq(nil)
154
+ expect(@employee3.test_boolean_before_type_cast).to be_nil
155
155
  create_employee3(test_boolean: "")
156
156
  expect(@employee3.test_boolean.class).to eq(NilClass)
157
- expect(@employee3.test_boolean_before_type_cast).to eq(nil)
157
+ expect(@employee3.test_boolean_before_type_cast).to be_nil
158
158
  end
159
159
 
160
160
  it "should return string value from VARCHAR2 column with boolean column name but attribute is set to :string" do