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,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter quoting" do
4
+ include LoggerSpecHelper
5
+ include SchemaSpecHelper
6
+
7
+ before(:all) do
8
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
9
+ end
10
+
11
+ describe "reserved words column quoting" do
12
+
13
+ before(:all) do
14
+ schema_define do
15
+ create_table :test_reserved_words do |t|
16
+ t.string :varchar2
17
+ t.integer :integer
18
+ t.text :comment
19
+ end
20
+ end
21
+ class ::TestReservedWord < ActiveRecord::Base; end
22
+ end
23
+
24
+ after(:all) do
25
+ schema_define do
26
+ drop_table :test_reserved_words
27
+ end
28
+ Object.send(:remove_const, "TestReservedWord")
29
+ ActiveRecord::Base.table_name_prefix = nil
30
+ ActiveRecord::Base.clear_cache!
31
+ end
32
+
33
+ before(:each) do
34
+ set_logger
35
+ end
36
+
37
+ after(:each) do
38
+ clear_logger
39
+ end
40
+
41
+ it "should create table" do
42
+ [:varchar2, :integer, :comment].each do |attr|
43
+ expect(TestReservedWord.columns_hash[attr.to_s].name).to eq(attr.to_s)
44
+ end
45
+ end
46
+
47
+ it "should create record" do
48
+ attrs = {
49
+ varchar2: "dummy",
50
+ integer: 1,
51
+ comment: "dummy"
52
+ }
53
+ record = TestReservedWord.create!(attrs)
54
+ record.reload
55
+ attrs.each do |k, v|
56
+ expect(record.send(k)).to eq(v)
57
+ end
58
+ end
59
+
60
+ it "should remove double quotes in column quoting" do
61
+ expect(ActiveRecord::Base.connection.quote_column_name('aaa "bbb" ccc')).to eq('"aaa bbb ccc"')
62
+ end
63
+
64
+ end
65
+
66
+ describe "valid table names" do
67
+ before(:all) do
68
+ @adapter = ActiveRecord::ConnectionAdapters::OracleEnhanced::Quoting
69
+ end
70
+
71
+ it "should be valid with letters and digits" do
72
+ expect(@adapter.valid_table_name?("abc_123")).to be_truthy
73
+ end
74
+
75
+ it "should be valid with schema name" do
76
+ expect(@adapter.valid_table_name?("abc_123.def_456")).to be_truthy
77
+ end
78
+
79
+ it "should be valid with schema name and object name in different case" do
80
+ expect(@adapter.valid_table_name?("TEST_DBA.def_456")).to be_truthy
81
+ end
82
+
83
+ it "should be valid with $ in name" do
84
+ expect(@adapter.valid_table_name?("sys.v$session")).to be_truthy
85
+ end
86
+
87
+ it "should be valid with upcase schema name" do
88
+ expect(@adapter.valid_table_name?("ABC_123.DEF_456")).to be_truthy
89
+ end
90
+
91
+ it "should be valid with irregular schema name and database links" do
92
+ expect(@adapter.valid_table_name?('abc$#_123.abc$#_123@abc$#@._123')).to be_truthy
93
+ end
94
+
95
+ it "should not be valid with two dots in name" do
96
+ expect(@adapter.valid_table_name?("abc_123.def_456.ghi_789")).to be_falsey
97
+ end
98
+
99
+ it "should not be valid with invalid characters" do
100
+ expect(@adapter.valid_table_name?("warehouse-things")).to be_falsey
101
+ end
102
+
103
+ it "should not be valid with for camel-case" do
104
+ expect(@adapter.valid_table_name?("Abc")).to be_falsey
105
+ expect(@adapter.valid_table_name?("aBc")).to be_falsey
106
+ expect(@adapter.valid_table_name?("abC")).to be_falsey
107
+ end
108
+
109
+ it "should not be valid for names > 30 characters" do
110
+ expect(@adapter.valid_table_name?("a" * 31)).to be_falsey
111
+ end
112
+
113
+ it "should not be valid for schema names > 30 characters" do
114
+ expect(@adapter.valid_table_name?(("a" * 31) + ".validname")).to be_falsey
115
+ end
116
+
117
+ it "should not be valid for database links > 128 characters" do
118
+ expect(@adapter.valid_table_name?("name@" + "a" * 129)).to be_falsey
119
+ end
120
+
121
+ it "should not be valid for names that do not begin with alphabetic characters" do
122
+ expect(@adapter.valid_table_name?("1abc")).to be_falsey
123
+ expect(@adapter.valid_table_name?("_abc")).to be_falsey
124
+ expect(@adapter.valid_table_name?("abc.1xyz")).to be_falsey
125
+ expect(@adapter.valid_table_name?("abc._xyz")).to be_falsey
126
+ end
127
+ end
128
+
129
+ describe "table quoting" do
130
+
131
+ def create_warehouse_things_table
132
+ ActiveRecord::Schema.define do
133
+ suppress_messages do
134
+ create_table "warehouse-things" do |t|
135
+ t.string :name
136
+ t.integer :foo
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ def create_camel_case_table
143
+ ActiveRecord::Schema.define do
144
+ suppress_messages do
145
+ create_table "CamelCase" do |t|
146
+ t.string :name
147
+ t.integer :foo
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ before(:all) do
154
+ @conn = ActiveRecord::Base.connection
155
+ end
156
+
157
+ after(:each) do
158
+ ActiveRecord::Schema.define do
159
+ suppress_messages do
160
+ drop_table "warehouse-things", if_exists: true
161
+ drop_table "CamelCase", if_exists: true
162
+ end
163
+ end
164
+ Object.send(:remove_const, "WarehouseThing") rescue nil
165
+ Object.send(:remove_const, "CamelCase") rescue nil
166
+ end
167
+
168
+ it "should allow creation of a table with non alphanumeric characters" do
169
+ create_warehouse_things_table
170
+ class ::WarehouseThing < ActiveRecord::Base
171
+ self.table_name = "warehouse-things"
172
+ end
173
+
174
+ wh = WarehouseThing.create!(name: "Foo", foo: 2)
175
+ expect(wh.id).not_to be_nil
176
+
177
+ expect(@conn.tables).to include("warehouse-things")
178
+ end
179
+
180
+ it "should allow creation of a table with CamelCase name" do
181
+ create_camel_case_table
182
+ class ::CamelCase < ActiveRecord::Base
183
+ self.table_name = "CamelCase"
184
+ end
185
+
186
+ cc = CamelCase.create!(name: "Foo", foo: 2)
187
+ expect(cc.id).not_to be_nil
188
+
189
+ expect(@conn.tables).to include("CamelCase")
190
+ end
191
+
192
+ it "properly quotes database links" do
193
+ expect(@conn.quote_table_name("asdf@some.link")).to eq('"ASDF"@"SOME.LINK"')
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,492 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe "OracleEnhancedAdapter schema dump" do
4
+ include SchemaSpecHelper
5
+ include SchemaDumpingHelper
6
+
7
+ before(:all) do
8
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
9
+ @conn = ActiveRecord::Base.connection
10
+ @oracle11g_or_higher = !! @conn.select_value(
11
+ "select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) >= 11")
12
+ end
13
+
14
+ def standard_dump(options = {})
15
+ stream = StringIO.new
16
+ ActiveRecord::SchemaDumper.ignore_tables = options[:ignore_tables] || []
17
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
18
+ stream.string
19
+ end
20
+
21
+ def create_test_posts_table(options = {})
22
+ options.merge! force: true
23
+ schema_define do
24
+ create_table :test_posts, options do |t|
25
+ t.string :title
26
+ t.timestamps null: true
27
+ end
28
+ add_index :test_posts, :title
29
+ end
30
+ end
31
+
32
+ def drop_test_posts_table
33
+ schema_define do
34
+ drop_table :test_posts
35
+ end
36
+ rescue
37
+ nil
38
+ end
39
+
40
+ describe "tables" do
41
+ after(:each) do
42
+ drop_test_posts_table
43
+ end
44
+
45
+ it "should not include ignored table names in schema dump" do
46
+ create_test_posts_table
47
+ expect(standard_dump(ignore_tables: %w(test_posts))).not_to match(/create_table "test_posts"/)
48
+ end
49
+
50
+ it "should not include ignored table regexes in schema dump" do
51
+ create_test_posts_table
52
+ expect(standard_dump(ignore_tables: [ /test_posts/i ])).not_to match(/create_table "test_posts"/)
53
+ end
54
+
55
+ end
56
+
57
+ describe "dumping default values" do
58
+ before :each do
59
+ schema_define do
60
+ create_table "test_defaults", force: true do |t|
61
+ t.string "regular", default: "c"
62
+ t.string "special_c", default: "\n"
63
+ end
64
+ end
65
+ end
66
+
67
+ after(:each) do
68
+ schema_define do
69
+ drop_table "test_defaults"
70
+ end
71
+ end
72
+
73
+ it "should be able to dump default values using special characters" do
74
+ output = dump_table_schema "test_defaults"
75
+ expect(output).to match(/t.string \"special_c\", default: "\\n"/)
76
+ end
77
+ end
78
+
79
+ describe "table with non-default primary key" do
80
+ after(:each) do
81
+ drop_test_posts_table
82
+ end
83
+
84
+ it "should include non-default primary key in schema dump" do
85
+ create_test_posts_table(primary_key: "post_id")
86
+ output = dump_table_schema "test_posts"
87
+ expect(output).to match(/create_table "test_posts", primary_key: "post_id"/)
88
+ end
89
+
90
+ end
91
+
92
+ describe "table with ntext columns" do
93
+ before :each do
94
+ schema_define do
95
+ create_table "test_ntexts", force: true do |t|
96
+ t.ntext :ntext_column
97
+ end
98
+ end
99
+ end
100
+
101
+ after(:each) do
102
+ schema_define do
103
+ drop_table "test_ntexts"
104
+ end
105
+ end
106
+
107
+ it "should be able to dump ntext columns" do
108
+ output = dump_table_schema "test_ntexts"
109
+ expect(output).to match(/t.ntext \"ntext_column\"/)
110
+ end
111
+ end
112
+
113
+ describe "table with primary key trigger" do
114
+
115
+ after(:each) do
116
+ drop_test_posts_table
117
+ end
118
+
119
+ it "should include primary key trigger in schema dump" do
120
+ create_test_posts_table(primary_key_trigger: true)
121
+ expect(standard_dump).to match(/create_table "test_posts".*add_primary_key_trigger "test_posts"/m)
122
+ end
123
+
124
+ it "should include primary key trigger with non-default primary key in schema dump" do
125
+ create_test_posts_table(primary_key_trigger: true, primary_key: "post_id")
126
+ expect(standard_dump).to match(/create_table "test_posts", primary_key: "post_id".*add_primary_key_trigger "test_posts", primary_key: "post_id"/m)
127
+ end
128
+
129
+ end
130
+
131
+ describe "foreign key constraints" do
132
+ before(:all) do
133
+ schema_define do
134
+ create_table :test_posts, force: true do |t|
135
+ t.string :title
136
+ end
137
+ create_table :test_comments, force: true do |t|
138
+ t.string :body, limit: 4000
139
+ t.references :test_post
140
+ end
141
+ end
142
+ end
143
+
144
+ after(:each) do
145
+ schema_define do
146
+ remove_foreign_key :test_comments, :test_posts rescue nil
147
+ remove_foreign_key :test_comments, name: "comments_posts_baz_fooz_fk" rescue nil
148
+ end
149
+ end
150
+ after(:all) do
151
+ schema_define do
152
+ drop_table :test_comments, if_exists: true
153
+ drop_table :test_posts, if_exists: true
154
+ end
155
+ end
156
+
157
+ it "should include foreign key in schema dump" do
158
+ schema_define do
159
+ add_foreign_key :test_comments, :test_posts
160
+ end
161
+ output = dump_table_schema "test_comments"
162
+ expect(output).to match(/add_foreign_key "test_comments", "test_posts"/)
163
+ end
164
+
165
+ it "should include foreign key with delete dependency in schema dump" do
166
+ schema_define do
167
+ add_foreign_key :test_comments, :test_posts, on_delete: :cascade
168
+ end
169
+ output = dump_table_schema "test_comments"
170
+ expect(output).to match(/add_foreign_key "test_comments", "test_posts", on_delete: :cascade/)
171
+ end
172
+
173
+ it "should include foreign key with nullify dependency in schema dump" do
174
+ schema_define do
175
+ add_foreign_key :test_comments, :test_posts, on_delete: :nullify
176
+ end
177
+ output = dump_table_schema "test_comments"
178
+ expect(output).to match(/add_foreign_key "test_comments", "test_posts", on_delete: :nullify/)
179
+ end
180
+
181
+ it "should not include foreign keys on ignored table names in schema dump" do
182
+ schema_define do
183
+ add_foreign_key :test_comments, :test_posts
184
+ end
185
+ expect(standard_dump(ignore_tables: %w(test_comments))).not_to match(/add_foreign_key "test_comments"/)
186
+ end
187
+
188
+ it "should not include foreign keys on ignored table regexes in schema dump" do
189
+ schema_define do
190
+ add_foreign_key :test_comments, :test_posts
191
+ end
192
+ expect(standard_dump(ignore_tables: [ /test_comments/i ])).not_to match(/add_foreign_key "test_comments"/)
193
+ end
194
+
195
+ it "should include foreign keys referencing ignored table names in schema dump" do
196
+ schema_define do
197
+ add_foreign_key :test_comments, :test_posts
198
+ end
199
+ expect(standard_dump(ignore_tables: %w(test_posts))).to match(/add_foreign_key "test_comments"/)
200
+ end
201
+
202
+ it "should include foreign keys referencing ignored table regexes in schema dump" do
203
+ schema_define do
204
+ add_foreign_key :test_comments, :test_posts
205
+ end
206
+ expect(standard_dump(ignore_tables: [ /test_posts/i ])).to match(/add_foreign_key "test_comments"/)
207
+ end
208
+
209
+ it "should include foreign keys following all tables" do
210
+ # if foreign keys precede declaration of all tables
211
+ # it can cause problems when using db:test rake tasks
212
+ schema_define do
213
+ add_foreign_key :test_comments, :test_posts
214
+ end
215
+ dump = standard_dump
216
+ expect(dump.rindex("create_table")).to be < dump.index("add_foreign_key")
217
+ end
218
+
219
+ it "should include primary_key when reference column name is not 'id'" do
220
+ schema_define do
221
+ create_table :test_posts, force: true, primary_key: "baz_id" do |t|
222
+ t.string :title
223
+ end
224
+ create_table :test_comments, force: true do |t|
225
+ t.string :body, limit: 4000
226
+ t.integer :baz_id
227
+ end
228
+ end
229
+
230
+ @conn.execute <<-SQL
231
+ ALTER TABLE TEST_COMMENTS
232
+ ADD CONSTRAINT TEST_COMMENTS_BAZ_ID_FK FOREIGN KEY (baz_id) REFERENCES test_posts(baz_id)
233
+ SQL
234
+
235
+ output = dump_table_schema "test_comments"
236
+ expect(output).to match(/add_foreign_key "test_comments", "test_posts", column: "baz_id", primary_key: "baz_id", name: "test_comments_baz_id_fk"/)
237
+ end
238
+
239
+ end
240
+
241
+ describe "synonyms" do
242
+ after(:each) do
243
+ schema_define do
244
+ remove_synonym :test_synonym
245
+ end
246
+ end
247
+
248
+ it "should include synonym to other schema table in schema dump" do
249
+ schema_define do
250
+ add_synonym :test_synonym, "schema_name.table_name", force: true
251
+ end
252
+ expect(standard_dump).to match(/add_synonym "test_synonym", "schema_name.table_name", force: true/)
253
+ end
254
+
255
+ it "should include synonym to other database table in schema dump" do
256
+ schema_define do
257
+ add_synonym :test_synonym, "table_name@link_name", force: true
258
+ end
259
+ expect(standard_dump).to match(/add_synonym "test_synonym", "table_name@link_name(\.[-A-Za-z0-9_]+)*", force: true/)
260
+ end
261
+
262
+ it "should not include ignored table names in schema dump" do
263
+ schema_define do
264
+ add_synonym :test_synonym, "schema_name.table_name", force: true
265
+ end
266
+ expect(standard_dump(ignore_tables: %w(test_synonym))).not_to match(/add_synonym "test_synonym"/)
267
+ end
268
+
269
+ it "should not include ignored table regexes in schema dump" do
270
+ schema_define do
271
+ add_synonym :test_synonym, "schema_name.table_name", force: true
272
+ end
273
+ expect(standard_dump(ignore_tables: [ /test_synonym/i ])).not_to match(/add_synonym "test_synonym"/)
274
+ end
275
+
276
+ it "should include synonyms to ignored table regexes in schema dump" do
277
+ schema_define do
278
+ add_synonym :test_synonym, "schema_name.table_name", force: true
279
+ end
280
+ expect(standard_dump(ignore_tables: [ /table_name/i ])).to match(/add_synonym "test_synonym"/)
281
+ end
282
+
283
+ end
284
+
285
+ describe "temporary tables" do
286
+ after(:each) do
287
+ drop_test_posts_table
288
+ end
289
+
290
+ it "should include temporary options" do
291
+ create_test_posts_table(temporary: true)
292
+ output = dump_table_schema "test_posts"
293
+ expect(output).to match(/create_table "test_posts", temporary: true/)
294
+ end
295
+ end
296
+
297
+ describe "indexes" do
298
+ after(:each) do
299
+ drop_test_posts_table
300
+ end
301
+
302
+ it "should not specify default tablespace in add index" do
303
+ create_test_posts_table
304
+ output = dump_table_schema "test_posts"
305
+ expect(output).to match(/t\.index \["title"\], name: "index_test_posts_on_title"$/)
306
+ end
307
+
308
+ it "should specify non-default tablespace in add index" do
309
+ tablespace_name = @conn.default_tablespace
310
+ allow(@conn).to receive(:default_tablespace).and_return("dummy")
311
+ create_test_posts_table
312
+ output = dump_table_schema "test_posts"
313
+ expect(output).to match(/t\.index \["title"\], name: "index_test_posts_on_title", tablespace: "#{tablespace_name}"$/)
314
+ end
315
+
316
+ it "should create and dump function-based indexes" do
317
+ create_test_posts_table
318
+ @conn.add_index :test_posts, "NVL(created_at, updated_at)", name: "index_test_posts_cr_upd_at"
319
+ output = dump_table_schema "test_posts"
320
+ expect(output).to match(/t\.index \["NVL\(\\"CREATED_AT\\",\\"UPDATED_AT\\"\)"\], name: "index_test_posts_cr_upd_at"$/)
321
+ end
322
+
323
+ end
324
+
325
+ describe "materialized views" do
326
+ after(:each) do
327
+ @conn.execute "DROP MATERIALIZED VIEW test_posts_mv" rescue nil
328
+ drop_test_posts_table
329
+ end
330
+
331
+ it "should not include materialized views in schema dump" do
332
+ create_test_posts_table
333
+ @conn.execute "CREATE MATERIALIZED VIEW test_posts_mv AS SELECT * FROM test_posts"
334
+ expect(standard_dump).not_to match(/create_table "test_posts_mv"/)
335
+ end
336
+ end
337
+
338
+ describe "virtual columns" do
339
+ before(:all) do
340
+ skip "Not supported in this database version" unless @oracle11g_or_higher
341
+ schema_define do
342
+ create_table :test_names, force: true do |t|
343
+ t.string :first_name
344
+ t.string :last_name
345
+ t.virtual :full_name, as: "first_name || ', ' || last_name"
346
+ t.virtual :short_name, as: "COALESCE(first_name, last_name)", type: :string, limit: 300
347
+ t.virtual :abbrev_name, as: "SUBSTR(first_name,1,50) || ' ' || SUBSTR(last_name,1,1) || '.'", type: "VARCHAR(100)"
348
+ t.virtual :name_ratio, as: "(LENGTH(first_name)*10/LENGTH(last_name)*10)"
349
+ t.column :full_name_length, :virtual, as: "length(first_name || ', ' || last_name)", type: :integer
350
+ t.virtual :field_with_leading_space, as: "' ' || first_name || ' '", limit: 300, type: :string
351
+ end
352
+ end
353
+ end
354
+
355
+ before(:each) do
356
+ if @oracle11g_or_higher
357
+ class ::TestName < ActiveRecord::Base
358
+ self.table_name = "test_names"
359
+ end
360
+ end
361
+ end
362
+
363
+ after(:all) do
364
+ if @oracle11g_or_higher
365
+ schema_define do
366
+ drop_table :test_names
367
+ end
368
+ end
369
+ end
370
+
371
+ it "should dump correctly" do
372
+ output = dump_table_schema "test_names"
373
+ expect(output).to match(/t\.virtual "full_name",(\s*)type: :string,(\s*)limit: 512,(\s*)as: "\\"FIRST_NAME\\"\|\|', '\|\|\\"LAST_NAME\\""/)
374
+ expect(output).to match(/t\.virtual "short_name",(\s*)type: :string,(\s*)limit: 300,(\s*)as:(.*)/)
375
+ expect(output).to match(/t\.virtual "full_name_length",(\s*)type: :integer,(\s*)precision: 38,(\s*)as:(.*)/)
376
+ expect(output).to match(/t\.virtual "name_ratio",(\s*)as:(.*)\"$/) # no :type
377
+ expect(output).to match(/t\.virtual "abbrev_name",(\s*)type: :string,(\s*)limit: 100,(\s*)as:(.*)/)
378
+ expect(output).to match(/t\.virtual "field_with_leading_space",(\s*)type: :string,(\s*)limit: 300,(\s*)as: "' '\|\|\\"FIRST_NAME\\"\|\|' '"/)
379
+ end
380
+
381
+ context "with index on virtual column" do
382
+ before(:all) do
383
+ if @oracle11g_or_higher
384
+ schema_define do
385
+ add_index "test_names", "field_with_leading_space", name: "index_on_virtual_col"
386
+ end
387
+ end
388
+ end
389
+ after(:all) do
390
+ if @oracle11g_or_higher
391
+ schema_define do
392
+ remove_index "test_names", name: "index_on_virtual_col"
393
+ end
394
+ end
395
+ end
396
+ it "should dump correctly" do
397
+ output = dump_table_schema "test_names"
398
+ expect(output).not_to match(/t\.index .+FIRST_NAME.+$/)
399
+ expect(output).to match(/t\.index .+field_with_leading_space.+$/)
400
+ end
401
+ end
402
+ end
403
+
404
+ describe ":float datatype" do
405
+ before(:each) do
406
+ schema_define do
407
+ create_table :test_floats, force: true do |t|
408
+ t.float :hourly_rate
409
+ end
410
+ end
411
+ end
412
+
413
+ after(:each) do
414
+ schema_define do
415
+ drop_table :test_floats
416
+ end
417
+ end
418
+
419
+ it "should dump float type correctly" do
420
+ output = dump_table_schema "test_floats"
421
+ expect(output).to match(/t\.float "hourly_rate"$/)
422
+ end
423
+ end
424
+
425
+ describe "table comments" do
426
+ before(:each) do
427
+ schema_define do
428
+ create_table :test_table_comments, comment: "this is a \"table comment\"!", force: true do |t|
429
+ t.string :blah
430
+ end
431
+ end
432
+ end
433
+
434
+ after(:each) do
435
+ schema_define do
436
+ drop_table :test_table_comments
437
+ end
438
+ end
439
+
440
+ it "should dump table comments" do
441
+ output = dump_table_schema "test_table_comments"
442
+ expect(output).to match(/create_table "test_table_comments", comment: "this is a \\"table comment\\"!", force: :cascade do \|t\|$/)
443
+ end
444
+ end
445
+
446
+ describe "column comments" do
447
+ before(:each) do
448
+ schema_define do
449
+ create_table :test_column_comments, force: true do |t|
450
+ t.string :blah, comment: "this is a \"column comment\"!"
451
+ end
452
+ end
453
+ end
454
+
455
+ after(:each) do
456
+ schema_define do
457
+ drop_table :test_column_comments
458
+ end
459
+ end
460
+
461
+ it "should dump column comments" do
462
+ output = dump_table_schema "test_column_comments"
463
+ expect(output).to match(/comment: "this is a \\"column comment\\"!"/)
464
+ end
465
+ end
466
+
467
+ describe "schema.rb format" do
468
+ before do
469
+ create_test_posts_table
470
+
471
+ schema_define do
472
+ create_table :test_comments, force: true do |t|
473
+ t.string :title
474
+ end
475
+
476
+ add_index :test_comments, :title
477
+ end
478
+ end
479
+
480
+ it "should be only one blank line between create_table methods in schema dump" do
481
+ expect(standard_dump).to match(/end\n\n create_table/)
482
+ end
483
+
484
+ after do
485
+ schema_define do
486
+ drop_table :test_comments, if_exists: true
487
+ end
488
+
489
+ drop_test_posts_table
490
+ end
491
+ end
492
+ end