activerecord-oracle_enhanced-adapter 1.4.3 → 5.2.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 (100) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +1162 -2
  3. data/README.md +567 -155
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +3 -1
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +19 -0
  7. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +132 -0
  8. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +345 -0
  9. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +52 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +280 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +64 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +59 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +538 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +46 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +435 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +196 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +164 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +95 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +79 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +194 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +709 -0
  24. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +28 -0
  25. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +353 -0
  26. data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +33 -0
  27. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +3 -0
  28. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +385 -1083
  29. data/lib/active_record/type/oracle_enhanced/boolean.rb +20 -0
  30. data/lib/active_record/type/oracle_enhanced/integer.rb +15 -0
  31. data/lib/active_record/type/oracle_enhanced/json.rb +10 -0
  32. data/lib/active_record/type/oracle_enhanced/national_character_string.rb +26 -0
  33. data/lib/active_record/type/oracle_enhanced/national_character_text.rb +36 -0
  34. data/lib/active_record/type/oracle_enhanced/raw.rb +25 -0
  35. data/lib/active_record/type/oracle_enhanced/string.rb +29 -0
  36. data/lib/active_record/type/oracle_enhanced/text.rb +32 -0
  37. data/lib/active_record/type/oracle_enhanced/timestampltz.rb +25 -0
  38. data/lib/active_record/type/oracle_enhanced/timestamptz.rb +25 -0
  39. data/lib/activerecord-oracle_enhanced-adapter.rb +5 -13
  40. data/spec/active_record/connection_adapters/{oracle_enhanced_emulate_oracle_adapter_spec.rb → emulation/oracle_adapter_spec.rb} +5 -4
  41. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +469 -0
  42. data/spec/active_record/connection_adapters/{oracle_enhanced_context_index_spec.rb → oracle_enhanced/context_index_spec.rb} +140 -128
  43. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +112 -0
  44. data/spec/active_record/connection_adapters/{oracle_enhanced_dbms_output_spec.rb → oracle_enhanced/dbms_output_spec.rb} +13 -13
  45. data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +365 -0
  46. data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +196 -0
  47. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +492 -0
  48. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +1433 -0
  49. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +478 -0
  50. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +385 -550
  51. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +92 -1249
  52. data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
  53. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +208 -0
  54. data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +139 -0
  55. data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
  56. data/spec/active_record/oracle_enhanced/type/integer_spec.rb +91 -0
  57. data/spec/active_record/oracle_enhanced/type/json_spec.rb +57 -0
  58. data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +55 -0
  59. data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +230 -0
  60. data/spec/active_record/oracle_enhanced/type/raw_spec.rb +122 -0
  61. data/spec/active_record/oracle_enhanced/type/text_spec.rb +229 -0
  62. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +75 -0
  63. data/spec/spec_config.yaml.template +11 -0
  64. data/spec/spec_helper.rb +100 -93
  65. data/spec/support/alter_system_set_open_cursors.sql +1 -0
  66. data/spec/support/alter_system_user_password.sql +2 -0
  67. data/spec/support/create_oracle_enhanced_users.sql +31 -0
  68. metadata +105 -152
  69. data/.rspec +0 -2
  70. data/Gemfile +0 -52
  71. data/RUNNING_TESTS.md +0 -45
  72. data/Rakefile +0 -59
  73. data/activerecord-oracle_enhanced-adapter.gemspec +0 -130
  74. data/lib/active_record/connection_adapters/oracle_enhanced.rake +0 -105
  75. data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
  76. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -121
  77. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +0 -151
  78. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +0 -119
  79. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -359
  80. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +0 -25
  81. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +0 -21
  82. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -46
  83. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +0 -572
  84. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +0 -497
  85. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +0 -260
  86. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -227
  87. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +0 -260
  88. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -428
  89. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -258
  90. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +0 -294
  91. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
  92. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
  93. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +0 -334
  94. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +0 -19
  95. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
  96. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +0 -141
  97. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +0 -378
  98. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +0 -440
  99. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +0 -1400
  100. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +0 -339
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter handling of BLOB columns" 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 do |t|
11
+ t.string :first_name, limit: 20
12
+ t.string :last_name, limit: 25
13
+ t.binary :binary_data
14
+ end
15
+ end
16
+ class ::TestEmployee < ActiveRecord::Base
17
+ end
18
+ @binary_data = "\0\1\2\3\4\5\6\7\8\9" * 10000
19
+ @binary_data2 = "\1\2\3\4\5\6\7\8\9\0" * 10000
20
+ end
21
+
22
+ after(:all) do
23
+ @conn.drop_table :test_employees, if_exists: true
24
+ Object.send(:remove_const, "TestEmployee")
25
+ end
26
+
27
+ after(:each) do
28
+ ActiveRecord::Base.clear_cache!
29
+ end
30
+
31
+ it "should create record with BLOB data" do
32
+ @employee = TestEmployee.create!(
33
+ first_name: "First",
34
+ last_name: "Last",
35
+ binary_data: @binary_data
36
+ )
37
+ @employee.reload
38
+ expect(@employee.binary_data).to eq(@binary_data)
39
+ end
40
+
41
+ it "should update record with BLOB data" do
42
+ @employee = TestEmployee.create!(
43
+ first_name: "First",
44
+ last_name: "Last"
45
+ )
46
+ @employee.reload
47
+ expect(@employee.binary_data).to be_nil
48
+ @employee.binary_data = @binary_data
49
+ @employee.save!
50
+ @employee.reload
51
+ expect(@employee.binary_data).to eq(@binary_data)
52
+ end
53
+
54
+ it "should update record with zero-length BLOB data" do
55
+ @employee = TestEmployee.create!(
56
+ first_name: "First",
57
+ last_name: "Last"
58
+ )
59
+ @employee.reload
60
+ expect(@employee.binary_data).to be_nil
61
+ @employee.binary_data = ""
62
+ @employee.save!
63
+ @employee.reload
64
+ expect(@employee.binary_data).to eq("")
65
+ end
66
+
67
+ it "should update record that has existing BLOB data with different BLOB data" do
68
+ @employee = TestEmployee.create!(
69
+ first_name: "First",
70
+ last_name: "Last",
71
+ binary_data: @binary_data
72
+ )
73
+ @employee.reload
74
+ @employee.binary_data = @binary_data2
75
+ @employee.save!
76
+ @employee.reload
77
+ expect(@employee.binary_data).to eq(@binary_data2)
78
+ end
79
+
80
+ it "should update record that has existing BLOB data with nil" do
81
+ @employee = TestEmployee.create!(
82
+ first_name: "First",
83
+ last_name: "Last",
84
+ binary_data: @binary_data
85
+ )
86
+ @employee.reload
87
+ @employee.binary_data = nil
88
+ @employee.save!
89
+ @employee.reload
90
+ expect(@employee.binary_data).to be_nil
91
+ end
92
+
93
+ it "should update record that has existing BLOB data with zero-length BLOB data" do
94
+ @employee = TestEmployee.create!(
95
+ first_name: "First",
96
+ last_name: "Last",
97
+ binary_data: @binary_data
98
+ )
99
+ @employee.reload
100
+ @employee.binary_data = ""
101
+ @employee.save!
102
+ @employee.reload
103
+ expect(@employee.binary_data).to eq("")
104
+ end
105
+
106
+ it "should update record that has zero-length BLOB data with non-empty BLOB data" do
107
+ @employee = TestEmployee.create!(
108
+ first_name: "First",
109
+ last_name: "Last",
110
+ binary_data: ""
111
+ )
112
+ @employee.reload
113
+ expect(@employee.binary_data).to eq("")
114
+ @employee.binary_data = @binary_data
115
+ @employee.save!
116
+ @employee.reload
117
+ expect(@employee.binary_data).to eq(@binary_data)
118
+ end
119
+ end
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter boolean type detection based on string column types and names" do
4
+ before(:all) do
5
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
6
+ @conn = ActiveRecord::Base.connection
7
+ @conn.execute <<-SQL
8
+ CREATE TABLE test3_employees (
9
+ id NUMBER PRIMARY KEY,
10
+ first_name VARCHAR2(20),
11
+ last_name VARCHAR2(25),
12
+ email VARCHAR2(25),
13
+ phone_number VARCHAR2(20),
14
+ hire_date DATE,
15
+ job_id NUMBER,
16
+ salary NUMBER,
17
+ commission_pct NUMBER(2,2),
18
+ manager_id NUMBER(6),
19
+ department_id NUMBER(4,0),
20
+ created_at DATE,
21
+ has_email CHAR(1),
22
+ has_phone VARCHAR2(1) DEFAULT 'Y',
23
+ active_flag VARCHAR2(2),
24
+ manager_yn VARCHAR2(3) DEFAULT 'N',
25
+ test_boolean VARCHAR2(3)
26
+ )
27
+ SQL
28
+ @conn.execute <<-SQL
29
+ CREATE SEQUENCE test3_employees_seq MINVALUE 1
30
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
31
+ SQL
32
+ end
33
+
34
+ after(:all) do
35
+ @conn.execute "DROP TABLE test3_employees"
36
+ @conn.execute "DROP SEQUENCE test3_employees_seq"
37
+ end
38
+
39
+ before(:each) do
40
+ class ::Test3Employee < ActiveRecord::Base
41
+ end
42
+ end
43
+
44
+ after(:each) do
45
+ Object.send(:remove_const, "Test3Employee")
46
+ ActiveRecord::Base.clear_cache!
47
+ end
48
+
49
+ describe "default values in new records" do
50
+ context "when emulate_booleans_from_strings is false" do
51
+ before do
52
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
53
+ end
54
+
55
+ it "are Y or N" do
56
+ subject = Test3Employee.new
57
+ expect(subject.has_phone).to eq("Y")
58
+ expect(subject.manager_yn).to eq("N")
59
+ end
60
+ end
61
+
62
+ context "when emulate_booleans_from_strings is true" do
63
+ before do
64
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
65
+ end
66
+
67
+ it "are True or False" do
68
+ class ::Test3Employee < ActiveRecord::Base
69
+ attribute :has_phone, :boolean
70
+ attribute :manager_yn, :boolean, default: false
71
+ end
72
+ subject = Test3Employee.new
73
+ expect(subject.has_phone).to be_a(TrueClass)
74
+ expect(subject.manager_yn).to be_a(FalseClass)
75
+ end
76
+ end
77
+ end
78
+
79
+ it "should translate boolean type to NUMBER(1) if emulate_booleans_from_strings is false" do
80
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
81
+ sql_type = ActiveRecord::Base.connection.type_to_sql(:boolean)
82
+ expect(sql_type).to eq("NUMBER(1)")
83
+ end
84
+
85
+ describe "/ VARCHAR2 boolean values from ActiveRecord model" do
86
+ before(:each) do
87
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
88
+ end
89
+
90
+ after(:each) do
91
+ ActiveRecord::Base.clear_cache!
92
+ end
93
+
94
+ def create_employee3(params = {})
95
+ @employee3 = Test3Employee.create(
96
+ {
97
+ first_name: "First",
98
+ last_name: "Last",
99
+ has_email: true,
100
+ has_phone: false,
101
+ active_flag: true,
102
+ manager_yn: false
103
+ }.merge(params)
104
+ )
105
+ @employee3.reload
106
+ end
107
+
108
+ it "should return String value from VARCHAR2 boolean column if emulate_booleans_from_strings is false" do
109
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
110
+ create_employee3
111
+ %w(has_email has_phone active_flag manager_yn).each do |col|
112
+ expect(@employee3.send(col.to_sym).class).to eq(String)
113
+ end
114
+ end
115
+
116
+ it "should return boolean value from VARCHAR2 boolean column if emulate_booleans_from_strings is true" do
117
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
118
+ class ::Test3Employee < ActiveRecord::Base
119
+ attribute :has_email, :boolean
120
+ attribute :active_flag, :boolean
121
+ attribute :has_phone, :boolean, default: false
122
+ attribute :manager_yn, :boolean, default: false
123
+ end
124
+ create_employee3
125
+ %w(has_email active_flag).each do |col|
126
+ expect(@employee3.send(col.to_sym).class).to eq(TrueClass)
127
+ expect(@employee3.send((col + "_before_type_cast").to_sym)).to eq("Y")
128
+ end
129
+ %w(has_phone manager_yn).each do |col|
130
+ expect(@employee3.send(col.to_sym).class).to eq(FalseClass)
131
+ expect(@employee3.send((col + "_before_type_cast").to_sym)).to eq("N")
132
+ end
133
+ end
134
+
135
+ it "should return string value from VARCHAR2 column if it is not boolean column and emulate_booleans_from_strings is true" do
136
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
137
+ create_employee3
138
+ expect(@employee3.first_name.class).to eq(String)
139
+ end
140
+
141
+ it "should return boolean value from VARCHAR2 boolean column if attribute is set to :boolean" do
142
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
143
+ class ::Test3Employee < ActiveRecord::Base
144
+ attribute :test_boolean, :boolean
145
+ end
146
+ create_employee3(test_boolean: true)
147
+ expect(@employee3.test_boolean.class).to eq(TrueClass)
148
+ expect(@employee3.test_boolean_before_type_cast).to eq("Y")
149
+ create_employee3(test_boolean: false)
150
+ expect(@employee3.test_boolean.class).to eq(FalseClass)
151
+ expect(@employee3.test_boolean_before_type_cast).to eq("N")
152
+ create_employee3(test_boolean: nil)
153
+ expect(@employee3.test_boolean.class).to eq(NilClass)
154
+ expect(@employee3.test_boolean_before_type_cast).to eq(nil)
155
+ create_employee3(test_boolean: "")
156
+ expect(@employee3.test_boolean.class).to eq(NilClass)
157
+ expect(@employee3.test_boolean_before_type_cast).to eq(nil)
158
+ end
159
+
160
+ it "should return string value from VARCHAR2 column with boolean column name but attribute is set to :string" do
161
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
162
+ class ::Test3Employee < ActiveRecord::Base
163
+ attribute :active_flag, :string
164
+ end
165
+ create_employee3
166
+ expect(@employee3.active_flag.class).to eq(String)
167
+ end
168
+
169
+ end
170
+
171
+ end
172
+
173
+ describe "OracleEnhancedAdapter boolean support when emulate_booleans_from_strings = true" do
174
+ include SchemaSpecHelper
175
+
176
+ before(:all) do
177
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
178
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
179
+ schema_define do
180
+ create_table :posts, force: true do |t|
181
+ t.string :name, null: false
182
+ t.boolean :is_default, default: false
183
+ end
184
+ end
185
+ end
186
+
187
+ after(:all) do
188
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
189
+ end
190
+
191
+ before(:each) do
192
+ class ::Post < ActiveRecord::Base
193
+ attribute :is_default, :boolean
194
+ end
195
+ end
196
+
197
+ after(:each) do
198
+ Object.send(:remove_const, "Post")
199
+ ActiveRecord::Base.clear_cache!
200
+ end
201
+
202
+ it "boolean should not change after reload" do
203
+ post = Post.create(name: "Test 1", is_default: false)
204
+ expect(post.is_default).to be false
205
+ post.reload
206
+ expect(post.is_default).to be false
207
+ end
208
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter dirty object tracking" do
4
+ include SchemaSpecHelper
5
+
6
+ before(:all) do
7
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
8
+ schema_define do
9
+ create_table :test_employees, force: true do |t|
10
+ t.string :first_name, limit: 20
11
+ t.string :last_name, limit: 25
12
+ t.integer :job_id, limit: 6, null: true
13
+ t.decimal :salary, precision: 8, scale: 2
14
+ t.text :comments
15
+ t.date :hire_date
16
+ end
17
+ end
18
+
19
+ class TestEmployee < ActiveRecord::Base
20
+ end
21
+ end
22
+
23
+ after(:all) do
24
+ schema_define do
25
+ drop_table :test_employees
26
+ end
27
+ Object.send(:remove_const, "TestEmployee")
28
+ ActiveRecord::Base.clear_cache!
29
+ end
30
+
31
+ it "should not mark empty string (stored as NULL) as changed when reassigning it" do
32
+ @employee = TestEmployee.create!(first_name: "")
33
+ @employee.first_name = ""
34
+ expect(@employee).not_to be_changed
35
+ @employee.reload
36
+ @employee.first_name = ""
37
+ expect(@employee).not_to be_changed
38
+ end
39
+
40
+ it "should not mark empty integer (stored as NULL) as changed when reassigning it" do
41
+ @employee = TestEmployee.create!(job_id: "")
42
+ @employee.job_id = ""
43
+ expect(@employee).not_to be_changed
44
+ @employee.reload
45
+ @employee.job_id = ""
46
+ expect(@employee).not_to be_changed
47
+ end
48
+
49
+ it "should not mark empty decimal (stored as NULL) as changed when reassigning it" do
50
+ @employee = TestEmployee.create!(salary: "")
51
+ @employee.salary = ""
52
+ expect(@employee).not_to be_changed
53
+ @employee.reload
54
+ @employee.salary = ""
55
+ expect(@employee).not_to be_changed
56
+ end
57
+
58
+ it "should not mark empty text (stored as NULL) as changed when reassigning it" do
59
+ @employee = TestEmployee.create!(comments: nil)
60
+ @employee.comments = nil
61
+ expect(@employee).not_to be_changed
62
+ @employee.reload
63
+ @employee.comments = nil
64
+ expect(@employee).not_to be_changed
65
+ end
66
+
67
+ it "should not mark empty text (stored as empty_clob()) as changed when reassigning it" do
68
+ @employee = TestEmployee.create!(comments: "")
69
+ @employee.comments = ""
70
+ expect(@employee).not_to be_changed
71
+ @employee.reload
72
+ @employee.comments = ""
73
+ expect(@employee).not_to be_changed
74
+ end
75
+
76
+ it "should mark empty text (stored as empty_clob()) as changed when assigning nil to it" do
77
+ @employee = TestEmployee.create!(comments: "")
78
+ @employee.comments = nil
79
+ expect(@employee).to be_changed
80
+ @employee.reload
81
+ @employee.comments = nil
82
+ expect(@employee).to be_changed
83
+ end
84
+
85
+ it "should mark empty text (stored as NULL) as changed when assigning '' to it" do
86
+ @employee = TestEmployee.create!(comments: nil)
87
+ @employee.comments = ""
88
+ expect(@employee).to be_changed
89
+ @employee.reload
90
+ @employee.comments = ""
91
+ expect(@employee).to be_changed
92
+ end
93
+
94
+ it "should not mark empty date (stored as NULL) as changed when reassigning it" do
95
+ @employee = TestEmployee.create!(hire_date: "")
96
+ @employee.hire_date = ""
97
+ expect(@employee).not_to be_changed
98
+ @employee.reload
99
+ @employee.hire_date = ""
100
+ expect(@employee).not_to be_changed
101
+ end
102
+
103
+ it "should not mark integer as changed when reassigning it" do
104
+ @employee = TestEmployee.new
105
+ @employee.job_id = 0
106
+ expect(@employee.save!).to be_truthy
107
+
108
+ expect(@employee).not_to be_changed
109
+
110
+ @employee.job_id = "0"
111
+ expect(@employee).not_to be_changed
112
+ end
113
+
114
+ it "should not update unchanged CLOBs" do
115
+ @conn = nil
116
+ @connection = nil
117
+ @employee = TestEmployee.create!(
118
+ comments: "initial"
119
+ )
120
+ expect(@employee.save!).to be_truthy
121
+ @employee.reload
122
+ expect(@employee.comments).to eq("initial")
123
+
124
+ oci_conn = @conn.instance_variable_get("@connection")
125
+ class << oci_conn
126
+ def write_lob(lob, value, is_binary = false); raise "don't do this'"; end
127
+ end
128
+ expect { @employee.save! }.not_to raise_error
129
+ class << oci_conn
130
+ remove_method :write_lob
131
+ end
132
+ end
133
+
134
+ it "should be able to handle attributes which are not backed by a column" do
135
+ TestEmployee.create!(comments: "initial")
136
+ @employee = TestEmployee.select("#{TestEmployee.quoted_table_name}.*, 24 ranking").first
137
+ expect { @employee.ranking = 25 }.to_not raise_error
138
+ end
139
+ end