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,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter handling of BINARY_FLOAT 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 :test2_employees, force: true do |t|
11
+ t.string :first_name, limit: 20
12
+ t.string :last_name, limit: 25
13
+ t.string :email, limit: 25
14
+ t.string :phone_number, limit: 25
15
+ t.date :hire_date
16
+ t.integer :job_id
17
+ t.integer :salary
18
+ t.decimal :commission_pct, scale: 2, precision: 2
19
+ t.float :hourly_rate
20
+ t.integer :manager_id, limit: 6
21
+ t.integer :is_manager, limit: 1
22
+ t.decimal :department_id, scale: 0, precision: 4
23
+ t.timestamps
24
+ end
25
+ end
26
+ class ::Test2Employee < ActiveRecord::Base
27
+ end
28
+ end
29
+
30
+ after(:all) do
31
+ Object.send(:remove_const, "Test2Employee")
32
+ @conn.drop_table :test2_employees, if_exists: true
33
+ end
34
+
35
+ it "should set BINARY_FLOAT column type as float" do
36
+ columns = @conn.columns("test2_employees")
37
+ column = columns.detect { |c| c.name == "hourly_rate" }
38
+ expect(column.type).to eq(:float)
39
+ end
40
+
41
+ it "should BINARY_FLOAT column type returns an approximate value" do
42
+ employee = Test2Employee.create(hourly_rate: 4.4)
43
+
44
+ employee.reload
45
+
46
+ expect(employee.hourly_rate).to eq(4.400000095367432)
47
+ end
48
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter integer type detection based on attribute settings" do
4
+ before(:all) do
5
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
6
+ @conn = ActiveRecord::Base.connection
7
+ @conn.execute "DROP TABLE test2_employees" rescue nil
8
+ @conn.execute <<-SQL
9
+ CREATE TABLE test2_employees (
10
+ id NUMBER PRIMARY KEY,
11
+ first_name VARCHAR2(20),
12
+ last_name VARCHAR2(25),
13
+ email VARCHAR2(25),
14
+ phone_number VARCHAR2(20),
15
+ hire_date DATE,
16
+ job_id NUMBER,
17
+ salary NUMBER,
18
+ commission_pct NUMBER(2,2),
19
+ manager_id NUMBER(6),
20
+ is_manager NUMBER(1),
21
+ department_id NUMBER(4,0),
22
+ created_at DATE
23
+ )
24
+ SQL
25
+ @conn.execute "DROP SEQUENCE test2_employees_seq" rescue nil
26
+ @conn.execute <<-SQL
27
+ CREATE SEQUENCE test2_employees_seq MINVALUE 1
28
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
29
+ SQL
30
+ end
31
+
32
+ after(:all) do
33
+ @conn.execute "DROP TABLE test2_employees"
34
+ @conn.execute "DROP SEQUENCE test2_employees_seq"
35
+ end
36
+
37
+ describe "/ NUMBER values from ActiveRecord model" do
38
+ before(:each) do
39
+ class ::Test2Employee < ActiveRecord::Base
40
+ end
41
+ end
42
+
43
+ after(:each) do
44
+ Object.send(:remove_const, "Test2Employee")
45
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = true
46
+ ActiveRecord::Base.clear_cache!
47
+ end
48
+
49
+ def create_employee2
50
+ @employee2 = Test2Employee.create(
51
+ first_name: "First",
52
+ last_name: "Last",
53
+ job_id: 1,
54
+ is_manager: 1,
55
+ salary: 1000
56
+ )
57
+ @employee2.reload
58
+ end
59
+
60
+ it "should return BigDecimal value from NUMBER column if by default" do
61
+ create_employee2
62
+ expect(@employee2.job_id.class).to eq(BigDecimal)
63
+ end
64
+
65
+ it "should return Integer value from NUMBER column if attribute is set to integer" do
66
+ class ::Test2Employee < ActiveRecord::Base
67
+ attribute :job_id, :integer
68
+ end
69
+ create_employee2
70
+ expect(@employee2.job_id).to be_a(Integer)
71
+ end
72
+
73
+ it "should return Integer value from NUMBER column with integer value using _before_type_cast method" do
74
+ create_employee2
75
+ expect(@employee2.job_id_before_type_cast).to be_a(Integer)
76
+ end
77
+
78
+ it "should return Boolean value from NUMBER(1) column if emulate booleans is used" do
79
+ create_employee2
80
+ expect(@employee2.is_manager.class).to eq(TrueClass)
81
+ end
82
+
83
+ it "should return Integer value from NUMBER(1) column if attribute is set to integer" do
84
+ class ::Test2Employee < ActiveRecord::Base
85
+ attribute :is_manager, :integer
86
+ end
87
+ create_employee2
88
+ expect(@employee2.is_manager).to be_a(Integer)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter attribute API support for JSON type" do
4
+
5
+ include SchemaSpecHelper
6
+
7
+ before(:all) do
8
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
9
+ @conn = ActiveRecord::Base.connection
10
+ @oracle12c_or_higher = !! @conn.select_value(
11
+ "select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) >= 12")
12
+ skip "Not supported in this database version" unless @oracle12c_or_higher
13
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
14
+ schema_define do
15
+ create_table :test_posts, force: true do |t|
16
+ t.string :title
17
+ t.text :article
18
+ end
19
+ execute "alter table test_posts add constraint test_posts_title_is_json check (title is json)"
20
+ execute "alter table test_posts add constraint test_posts_article_is_json check (article is json)"
21
+ end
22
+
23
+ class ::TestPost < ActiveRecord::Base
24
+ attribute :title, :json
25
+ attribute :article, :json
26
+ end
27
+ end
28
+
29
+ after(:all) do
30
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
31
+ schema_define do
32
+ drop_table :test_posts, if_exists: true
33
+ end
34
+ end
35
+
36
+ before(:each) do
37
+ TestPost.delete_all
38
+ end
39
+
40
+ it "should support attribute api for JSON" do
41
+ post = TestPost.create!(title: { "publish" => true, "foo" => "bar" }, article: { "bar" => "baz" })
42
+ post.reload
43
+ expect(post.title).to eq ({ "publish" => true, "foo" => "bar" })
44
+ expect(post.article).to eq ({ "bar" => "baz" })
45
+ post.title = ({ "publish" => false, "foo" => "bar2" })
46
+ post.save
47
+ expect(post.reload.title).to eq ({ "publish" => false, "foo" => "bar2" })
48
+ end
49
+
50
+ it "should support IS JSON" do
51
+ TestPost.create!(title: { "publish" => true, "foo" => "bar" })
52
+ count_json = TestPost.where("title is json")
53
+ expect(count_json.size).to eq 1
54
+ count_non_json = TestPost.where("title is not json")
55
+ expect(count_non_json.size).to eq 0
56
+ end
57
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter quoting of NCHAR and NVARCHAR2 columns" do
4
+ before(:all) do
5
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
6
+ @conn = ActiveRecord::Base.connection
7
+ @conn.execute <<-SQL
8
+ CREATE TABLE test_items (
9
+ id NUMBER(6,0) PRIMARY KEY,
10
+ nchar_column NCHAR(20),
11
+ nvarchar2_column NVARCHAR2(20),
12
+ char_column CHAR(20),
13
+ varchar2_column VARCHAR2(20)
14
+ )
15
+ SQL
16
+ @conn.execute "CREATE SEQUENCE test_items_seq"
17
+ end
18
+
19
+ after(:all) do
20
+ @conn.execute "DROP TABLE test_items"
21
+ @conn.execute "DROP SEQUENCE test_items_seq"
22
+ end
23
+
24
+ before(:each) do
25
+ class ::TestItem < ActiveRecord::Base
26
+ end
27
+ end
28
+
29
+ after(:each) do
30
+ Object.send(:remove_const, "TestItem")
31
+ ActiveRecord::Base.clear_cache!
32
+ end
33
+
34
+ it "should quote with N prefix" do
35
+ columns = @conn.columns("test_items")
36
+ %w(nchar_column nvarchar2_column char_column varchar2_column).each do |col|
37
+ column = columns.detect { |c| c.name == col }
38
+ value = @conn.type_cast_from_column(column, "abc")
39
+ expect(@conn.quote(value)).to eq(column.sql_type[0, 1] == "N" ? "N'abc'" : "'abc'")
40
+ nilvalue = @conn.type_cast_from_column(column, nil)
41
+ expect(@conn.quote(nilvalue)).to eq("NULL")
42
+ end
43
+ end
44
+
45
+ it "should create record" do
46
+ nchar_data = "āčē"
47
+ item = TestItem.create(
48
+ nchar_column: nchar_data,
49
+ nvarchar2_column: nchar_data
50
+ ).reload
51
+ expect(item.nchar_column).to eq(nchar_data + " " * 17)
52
+ expect(item.nvarchar2_column).to eq(nchar_data)
53
+ end
54
+
55
+ end
@@ -0,0 +1,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter handling of NCLOB 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.ntext :comments
14
+ end
15
+ create_table :test2_employees, force: true do |t|
16
+ t.string :first_name, limit: 20
17
+ t.string :last_name, limit: 25
18
+ t.ntext :comments
19
+ end
20
+ create_table :test_serialize_employees, force: true do |t|
21
+ t.string :first_name, limit: 20
22
+ t.string :last_name, limit: 25
23
+ end
24
+ add_column :test_serialize_employees, :comments, :ntext
25
+ end
26
+
27
+ # Some random multibyte characters. They say Hello (Kon'nichiwa) World (Sekai) in Japanese.
28
+ @nclob_data = "こんにちは"
29
+ @nclob_data2 = "世界"
30
+
31
+ class ::TestEmployee < ActiveRecord::Base; end
32
+ class ::Test2Employee < ActiveRecord::Base
33
+ serialize :comments
34
+ end
35
+ class ::TestEmployeeReadOnlyNClob < ActiveRecord::Base
36
+ self.table_name = "test_employees"
37
+ attr_readonly :comments
38
+ end
39
+ class ::TestSerializeEmployee < ActiveRecord::Base
40
+ serialize :comments
41
+ attr_readonly :comments
42
+ end
43
+ end
44
+
45
+ after(:all) do
46
+ @conn.drop_table :test_employees, if_exists: true
47
+ @conn.drop_table :test2_employees, if_exists: true
48
+ @conn.drop_table :test_serialize_employees, if_exists: true
49
+ Object.send(:remove_const, "TestEmployee")
50
+ Object.send(:remove_const, "Test2Employee")
51
+ Object.send(:remove_const, "TestEmployeeReadOnlyNClob")
52
+ Object.send(:remove_const, "TestSerializeEmployee")
53
+ ActiveRecord::Base.clear_cache!
54
+ end
55
+
56
+ it "should create record without NCLOB data when attribute is serialized" do
57
+ @employee = Test2Employee.create!(
58
+ first_name: "First",
59
+ last_name: "Last"
60
+ )
61
+ expect(@employee).to be_valid
62
+ @employee.reload
63
+ expect(@employee.comments).to be_nil
64
+ end
65
+
66
+ it "should accept Symbol value for NCLOB column" do
67
+ @employee = TestEmployee.create!(
68
+ comments: :test_comment
69
+ )
70
+ expect(@employee).to be_valid
71
+ end
72
+
73
+ it "should respect attr_readonly setting for NCLOB column" do
74
+ @employee = TestEmployeeReadOnlyNClob.create!(
75
+ first_name: "First",
76
+ comments: @nclob_data
77
+ )
78
+ expect(@employee).to be_valid
79
+ @employee.reload
80
+ expect(@employee.comments).to eq(@nclob_data)
81
+ @employee.comments = @nclob_data2
82
+ expect(@employee.save).to eq(true)
83
+ @employee.reload
84
+ expect(@employee.comments).to eq(@nclob_data)
85
+ end
86
+
87
+ it "should work for serialized readonly NCLOB columns", serialized: true do
88
+ @employee = TestSerializeEmployee.new(
89
+ first_name: "First",
90
+ comments: nil
91
+ )
92
+ expect(@employee.comments).to be_nil
93
+ expect(@employee.save).to eq(true)
94
+ expect(@employee).to be_valid
95
+ @employee.reload
96
+ expect(@employee.comments).to be_nil
97
+ @employee.comments = {}
98
+ expect(@employee.save).to eq(true)
99
+ @employee.reload
100
+ # should not set readonly
101
+ expect(@employee.comments).to be_nil
102
+ end
103
+
104
+ it "should create record with NCLOB data" do
105
+ @employee = TestEmployee.create!(
106
+ first_name: "First",
107
+ last_name: "Last",
108
+ comments: @nclob_data
109
+ )
110
+ @employee.reload
111
+ expect(@employee.comments).to eq(@nclob_data)
112
+ end
113
+
114
+ it "should update record with NCLOB data" do
115
+ @employee = TestEmployee.create!(
116
+ first_name: "First",
117
+ last_name: "Last"
118
+ )
119
+ @employee.reload
120
+ expect(@employee.comments).to be_nil
121
+ @employee.comments = @nclob_data
122
+ @employee.save!
123
+ @employee.reload
124
+ expect(@employee.comments).to eq(@nclob_data)
125
+ end
126
+
127
+ it "should update record with zero-length NCLOB data" do
128
+ @employee = TestEmployee.create!(
129
+ first_name: "First",
130
+ last_name: "Last"
131
+ )
132
+ @employee.reload
133
+ expect(@employee.comments).to be_nil
134
+ @employee.comments = ""
135
+ @employee.save!
136
+ @employee.reload
137
+ expect(@employee.comments).to eq("")
138
+ end
139
+
140
+ it "should update record that has existing NCLOB data with different NCLOB data" do
141
+ @employee = TestEmployee.create!(
142
+ first_name: "First",
143
+ last_name: "Last",
144
+ comments: @nclob_data
145
+ )
146
+ @employee.reload
147
+ @employee.comments = @nclob_data2
148
+ @employee.save!
149
+ @employee.reload
150
+ expect(@employee.comments).to eq(@nclob_data2)
151
+ end
152
+
153
+ it "should update record that has existing NCLOB data with nil" do
154
+ @employee = TestEmployee.create!(
155
+ first_name: "First",
156
+ last_name: "Last",
157
+ comments: @nclob_data
158
+ )
159
+ @employee.reload
160
+ @employee.comments = nil
161
+ @employee.save!
162
+ @employee.reload
163
+ expect(@employee.comments).to be_nil
164
+ end
165
+
166
+ it "should update record that has existing NCLOB data with zero-length NCLOB data" do
167
+ @employee = TestEmployee.create!(
168
+ first_name: "First",
169
+ last_name: "Last",
170
+ comments: @nclob_data
171
+ )
172
+ @employee.reload
173
+ @employee.comments = ""
174
+ @employee.save!
175
+ @employee.reload
176
+ expect(@employee.comments).to eq("")
177
+ end
178
+
179
+ it "should update record that has zero-length NCLOB data with non-empty NCLOB data" do
180
+ @employee = TestEmployee.create!(
181
+ first_name: "First",
182
+ last_name: "Last",
183
+ comments: ""
184
+ )
185
+ @employee.reload
186
+ expect(@employee.comments).to eq("")
187
+ @employee.comments = @nclob_data
188
+ @employee.save!
189
+ @employee.reload
190
+ expect(@employee.comments).to eq(@nclob_data)
191
+ end
192
+
193
+ it "should store serializable ruby data structures" do
194
+ ruby_data1 = { "arbitrary1" => ["ruby", :data, 123] }
195
+ ruby_data2 = { "arbitrary2" => ["ruby", :data, 123] }
196
+ @employee = Test2Employee.create!(
197
+ comments: ruby_data1
198
+ )
199
+ @employee.reload
200
+ expect(@employee.comments).to eq(ruby_data1)
201
+ @employee.comments = ruby_data2
202
+ @employee.save
203
+ @employee.reload
204
+ expect(@employee.comments).to eq(ruby_data2)
205
+ end
206
+
207
+ it "should keep unchanged serialized data when other columns changed" do
208
+ @employee = Test2Employee.create!(
209
+ first_name: "First",
210
+ last_name: "Last",
211
+ comments: @nclob_data
212
+ )
213
+ @employee.first_name = "Steve"
214
+ @employee.save
215
+ @employee.reload
216
+ expect(@employee.comments).to eq(@nclob_data)
217
+ end
218
+
219
+ it "should keep serialized data after save" do
220
+ @employee = Test2Employee.new
221
+ @employee.comments = { length: { is: 1 } }
222
+ @employee.save
223
+ @employee.reload
224
+ expect(@employee.comments).to eq(length: { is: 1 })
225
+ @employee.comments = { length: { is: 2 } }
226
+ @employee.save
227
+ @employee.reload
228
+ expect(@employee.comments).to eq(length: { is: 2 })
229
+ end
230
+ end