activerecord-oracle_enhanced-adapter 7.0.0 → 7.1.1

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +64 -0
  3. data/README.md +11 -2
  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 +33 -24
  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 +73 -30
  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/compatibility_spec.rb +36 -0
  26. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +30 -5
  27. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +7 -2
  28. data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +2 -2
  29. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +3 -0
  30. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +53 -15
  31. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +15 -18
  32. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +14 -10
  33. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +2 -2
  34. data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +24 -0
  35. data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
  36. data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +4 -2
  37. data/spec/active_record/oracle_enhanced/type/integer_spec.rb +8 -0
  38. data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +3 -3
  39. data/spec/active_record/oracle_enhanced/type/raw_spec.rb +15 -0
  40. data/spec/active_record/oracle_enhanced/type/text_spec.rb +18 -3
  41. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +5 -1
  42. data/spec/spec_config.yaml.template +2 -2
  43. data/spec/spec_helper.rb +14 -3
  44. metadata +26 -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
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "compatibility migrations" do
4
+ include SchemaSpecHelper
5
+
6
+ before(:all) do
7
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
8
+ @conn = ActiveRecord::Base.connection
9
+ schema_define do
10
+ create_table :test_employees, force: true
11
+ end
12
+ end
13
+
14
+ after(:all) do
15
+ schema_define do
16
+ drop_table :test_employees, if_exists: true
17
+ drop_table :new_test_employees, if_exists: true
18
+ end
19
+ end
20
+
21
+ it "should rename table on 7_0 and below" do
22
+ migration = Class.new(ActiveRecord::Migration[7.0]) {
23
+ def change
24
+ rename_table :test_employees, :new_test_employees
25
+ end
26
+ }.new
27
+
28
+ migration.migrate(:up)
29
+ expect(@conn.table_exists?(:new_test_employees)).to be_truthy
30
+ expect(@conn.table_exists?(:test_employees)).not_to be_truthy
31
+
32
+ migration.migrate(:down)
33
+ expect(@conn.table_exists?(:new_test_employees)).not_to be_truthy
34
+ expect(@conn.table_exists?(:test_employees)).to be_truthy
35
+ end
36
+ end
@@ -30,6 +30,12 @@ describe "OracleEnhancedAdapter establish connection" do
30
30
  expect(ActiveRecord::Base.connection).to be_active
31
31
  end
32
32
 
33
+ it "should be active after reconnection to database with restore_transactions: true" do
34
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
35
+ ActiveRecord::Base.connection.reconnect!(restore_transactions: true)
36
+ expect(ActiveRecord::Base.connection).to be_active
37
+ end
38
+
33
39
  it "should use database default cursor_sharing parameter value force by default" do
34
40
  # Use `SYSTEM_CONNECTION_PARAMS` to query v$parameter
35
41
  ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS)
@@ -44,7 +50,7 @@ describe "OracleEnhancedAdapter establish connection" do
44
50
  it "should not use JDBC statement caching" do
45
51
  if ORACLE_ENHANCED_CONNECTION == :jdbc
46
52
  ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS)
47
- expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to eq(false)
53
+ expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to be(false)
48
54
  expect(ActiveRecord::Base.connection.raw_connection.getStatementCacheSize).to eq(-1)
49
55
  end
50
56
  end
@@ -52,12 +58,26 @@ describe "OracleEnhancedAdapter establish connection" do
52
58
  it "should use JDBC statement caching" do
53
59
  if ORACLE_ENHANCED_CONNECTION == :jdbc
54
60
  ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_statement_cache_size: 100))
55
- expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to eq(true)
61
+ expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to be(true)
56
62
  expect(ActiveRecord::Base.connection.raw_connection.getStatementCacheSize).to eq(100)
57
63
  # else: don't raise error if OCI connection has parameter "jdbc_statement_cache_size", still ignore it
58
64
  end
59
65
  end
60
66
 
67
+ it "should not encrypt JDBC network connection" do
68
+ if ORACLE_ENHANCED_CONNECTION == :jdbc
69
+ @conn = ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_connect_properties: { "oracle.net.encryption_client" => "REJECTED" }))
70
+ 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 }])
71
+ end
72
+ end
73
+
74
+ it "should encrypt JDBC network connection" do
75
+ if ORACLE_ENHANCED_CONNECTION == :jdbc
76
+ @conn = ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_connect_properties: { "oracle.net.encryption_client" => "REQUESTED" }))
77
+ 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 }])
78
+ end
79
+ end
80
+
61
81
  it "should connect to database using service_name" do
62
82
  ActiveRecord::Base.establish_connection(SERVICE_NAME_CONNECTION_PARAMS)
63
83
  expect(ActiveRecord::Base.connection).not_to be_nil
@@ -227,7 +247,7 @@ describe "OracleEnhancedConnection" do
227
247
  end
228
248
 
229
249
  after(:all) do
230
- Object.send(:remove_const, "Post")
250
+ Object.send(:remove_const, "Post") if defined?(Post)
231
251
  ActiveRecord::Base.clear_cache!
232
252
  end
233
253
 
@@ -392,7 +412,7 @@ describe "OracleEnhancedConnection" do
392
412
  @conn.exec "DROP TABLE test_employees" rescue nil
393
413
  end
394
414
 
395
- it "should execute prepared statement with decimal bind parameter " do
415
+ it "should execute prepared statement with decimal bind parameter" do
396
416
  cursor = @conn.prepare("INSERT INTO test_employees VALUES(:1)")
397
417
  type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "NUMBER", type: :decimal, limit: 10, precision: nil, scale: 2)
398
418
  column = ActiveRecord::ConnectionAdapters::OracleEnhanced::Column.new("age", nil, type_metadata, false, comment: nil)
@@ -414,7 +434,7 @@ describe "OracleEnhancedConnection" do
414
434
 
415
435
  before(:all) do
416
436
  ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
417
- @conn = ActiveRecord::Base.connection.instance_variable_get("@connection")
437
+ @conn = ActiveRecord::Base.connection.send(:_connection)
418
438
  @sys_conn = ActiveRecord::ConnectionAdapters::OracleEnhanced::Connection.create(SYS_CONNECTION_PARAMS)
419
439
  schema_define do
420
440
  create_table :posts, force: true
@@ -447,6 +467,11 @@ describe "OracleEnhancedConnection" do
447
467
  expect(@conn.exec("SELECT * FROM dual")).not_to be_nil
448
468
  end
449
469
 
470
+ it "should reconnect and execute SQL statement if connection is lost and allow_retry is passed" do
471
+ kill_current_session
472
+ expect(@conn.exec("SELECT * FROM dual", allow_retry: true)).not_to be_nil
473
+ end
474
+
450
475
  it "should not reconnect and execute SQL statement if connection is lost and auto retry is disabled" do
451
476
  # @conn.auto_retry = false
452
477
  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.+$/)
@@ -387,6 +387,34 @@ describe "OracleEnhancedAdapter schema definition" do
387
387
  end
388
388
  end
389
389
 
390
+ describe "add timestamps" do
391
+ before(:each) do
392
+ @conn = ActiveRecord::Base.connection
393
+ schema_define do
394
+ create_table :test_employees, force: true
395
+ end
396
+ class ::TestEmployee < ActiveRecord::Base; end
397
+ end
398
+
399
+ after(:each) do
400
+ schema_define do
401
+ drop_table :test_employees, if_exists: true
402
+ end
403
+ Object.send(:remove_const, "TestEmployee")
404
+ ActiveRecord::Base.clear_cache!
405
+ end
406
+
407
+ it "should add created_at and updated_at" do
408
+ expect do
409
+ @conn.add_timestamps("test_employees")
410
+ end.not_to raise_error
411
+
412
+ TestEmployee.reset_column_information
413
+ expect(TestEmployee.columns_hash["created_at"]).not_to be_nil
414
+ expect(TestEmployee.columns_hash["updated_at"]).not_to be_nil
415
+ end
416
+ end
417
+
390
418
  describe "ignore options for LOB columns" do
391
419
  after(:each) do
392
420
  schema_define do
@@ -550,6 +578,7 @@ end
550
578
  class ::TestPost < ActiveRecord::Base
551
579
  end
552
580
  end
581
+
553
582
  it "should use default tablespace for clobs" do
554
583
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = DATABASE_NON_DEFAULT_TABLESPACE
555
584
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = nil
@@ -880,7 +909,7 @@ end
880
909
  expect(TestPost.columns_hash["a" * 128]).not_to be_nil
881
910
  end
882
911
 
883
- it "should add lob column with non_default tablespace" do
912
+ it "should add text type lob column with non_default tablespace" do
884
913
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = DATABASE_NON_DEFAULT_TABLESPACE
885
914
  schema_define do
886
915
  add_column :test_posts, :body, :text
@@ -888,7 +917,7 @@ end
888
917
  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
918
  end
890
919
 
891
- it "should add lob column with non_default tablespace" do
920
+ it "should add ntext type lob column with non_default tablespace" do
892
921
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = DATABASE_NON_DEFAULT_TABLESPACE
893
922
  schema_define do
894
923
  add_column :test_posts, :body, :ntext
@@ -995,12 +1024,12 @@ end
995
1024
 
996
1025
  it "should include virtual columns and not try to update them" do
997
1026
  tf = TestFraction.columns.detect { |c| c.virtual? }
998
- expect(tf).not_to be nil
1027
+ expect(tf).not_to be_nil
999
1028
  expect(tf.name).to eq("percent")
1000
1029
  expect(tf.virtual?).to be true
1001
1030
  expect do
1002
1031
  tf = TestFraction.new(numerator: 20, denominator: 100)
1003
- expect(tf.percent).to be nil # not whatever is in DATA_DEFAULT column
1032
+ expect(tf.percent).to be_nil # not whatever is in DATA_DEFAULT column
1004
1033
  tf.save!
1005
1034
  tf.reload
1006
1035
  end.not_to raise_error
@@ -1013,11 +1042,11 @@ end
1013
1042
  end
1014
1043
  TestFraction.reset_column_information
1015
1044
  tf = TestFraction.columns.detect { |c| c.name == "rem" }
1016
- expect(tf).not_to be nil
1045
+ expect(tf).not_to be_nil
1017
1046
  expect(tf.virtual?).to be true
1018
1047
  expect do
1019
1048
  tf = TestFraction.new(numerator: 7, denominator: 5)
1020
- expect(tf.rem).to be nil
1049
+ expect(tf.rem).to be_nil
1021
1050
  tf.save!
1022
1051
  tf.reload
1023
1052
  end.not_to raise_error
@@ -1030,13 +1059,13 @@ end
1030
1059
  end
1031
1060
  TestFraction.reset_column_information
1032
1061
  tf = TestFraction.columns.detect { |c| c.name == "expression" }
1033
- expect(tf).not_to be nil
1062
+ expect(tf).not_to be_nil
1034
1063
  expect(tf.virtual?).to be true
1035
1064
  expect(tf.type).to be :string
1036
1065
  expect(tf.limit).to be 100
1037
1066
  expect do
1038
1067
  tf = TestFraction.new(numerator: 7, denominator: 5)
1039
- expect(tf.expression).to be nil
1068
+ expect(tf.expression).to be_nil
1040
1069
  tf.save!
1041
1070
  tf.reload
1042
1071
  end.not_to raise_error
@@ -1050,14 +1079,14 @@ end
1050
1079
  end
1051
1080
  TestFraction.reset_column_information
1052
1081
  tf = TestFraction.columns.detect { |c| c.name == "percent" }
1053
- expect(tf).not_to be nil
1082
+ expect(tf).not_to be_nil
1054
1083
  expect(tf.virtual?).to be true
1055
1084
  expect(tf.type).to be :decimal
1056
1085
  expect(tf.precision).to be 15
1057
1086
  expect(tf.scale).to be 2
1058
1087
  expect do
1059
1088
  tf = TestFraction.new(numerator: 11, denominator: 17)
1060
- expect(tf.percent).to be nil
1089
+ expect(tf.percent).to be_nil
1061
1090
  tf.save!
1062
1091
  tf.reload
1063
1092
  end.not_to raise_error
@@ -1070,14 +1099,14 @@ end
1070
1099
  end
1071
1100
  TestFraction.reset_column_information
1072
1101
  tf = TestFraction.columns.detect { |c| c.name == "percent" }
1073
- expect(tf).not_to be nil
1102
+ expect(tf).not_to be_nil
1074
1103
  expect(tf.virtual?).to be true
1075
1104
  expect(tf.type).to be :decimal
1076
1105
  expect(tf.precision).to be 12
1077
1106
  expect(tf.scale).to be 5
1078
1107
  expect do
1079
1108
  tf = TestFraction.new(numerator: 11, denominator: 17)
1080
- expect(tf.percent).to be nil
1109
+ expect(tf.percent).to be_nil
1081
1110
  tf.save!
1082
1111
  tf.reload
1083
1112
  end.not_to raise_error
@@ -1157,6 +1186,7 @@ end
1157
1186
  @conn.drop_table :tablespace_tests, if_exists: true
1158
1187
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:table)
1159
1188
  end
1189
+
1160
1190
  it "should use correct tablespace" do
1161
1191
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:table] = DATABASE_NON_DEFAULT_TABLESPACE
1162
1192
  @conn.create_table :tablespace_tests do |t|
@@ -1171,6 +1201,7 @@ end
1171
1201
  @conn.drop_table :tablespace_tests, if_exists: true
1172
1202
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:table)
1173
1203
  end
1204
+
1174
1205
  it "should use correct tablespace" do
1175
1206
  @conn.create_table :tablespace_tests, id: false, organization: "INDEX INITRANS 4 COMPRESS 1", tablespace: "bogus" do |t|
1176
1207
  t.integer :id
@@ -1206,7 +1237,14 @@ end
1206
1237
  schema_define do
1207
1238
  add_index :keyboards, "lower(name)", unique: true, name: :index_keyboards_on_lower_name
1208
1239
  end
1209
- expect(@would_execute_sql).not_to match(/ALTER +TABLE .* ADD CONSTRAINT .* UNIQUE \(.*\(.*\)\)/)
1240
+ expect(@would_execute_sql).not_to include("ADD CONSTRAINT")
1241
+ end
1242
+
1243
+ it "should add unique constraint only to the index where it was defined" do
1244
+ schema_define do
1245
+ add_index :keyboards, ["name"], unique: true, name: :this_index
1246
+ end
1247
+ expect(@would_execute_sql.lines.last).to match(/ALTER +TABLE .* ADD CONSTRAINT .* UNIQUE \(.*\) USING INDEX "THIS_INDEX";/)
1210
1248
  end
1211
1249
  end
1212
1250
 
@@ -1218,7 +1256,7 @@ end
1218
1256
  before do
1219
1257
  @conn = ActiveRecord::Base.connection
1220
1258
 
1221
- ActiveRecord::SchemaMigration.create_table
1259
+ ActiveRecord::Base.connection.schema_migration.create_table
1222
1260
  end
1223
1261
 
1224
1262
  context "multi insert is supported" do
@@ -1246,7 +1284,7 @@ end
1246
1284
  end
1247
1285
 
1248
1286
  after do
1249
- ActiveRecord::SchemaMigration.drop_table
1287
+ ActiveRecord::Base.connection.schema_migration.drop_table
1250
1288
  end
1251
1289
  end
1252
1290
  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/)