activerecord-oracle_enhanced-adapter 1.7.11 → 1.8.2

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +206 -4
  3. data/README.md +37 -1
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +1 -1
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +7 -59
  7. data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +6 -50
  8. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +11 -11
  9. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +117 -117
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +37 -27
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +10 -10
  12. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +56 -71
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +0 -7
  14. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +51 -69
  15. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +4 -4
  16. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +76 -76
  17. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +14 -43
  18. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +60 -64
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +33 -47
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +150 -160
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +95 -133
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +3 -3
  23. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +66 -101
  24. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -1
  25. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +290 -533
  26. data/lib/active_record/oracle_enhanced/type/boolean.rb +7 -10
  27. data/lib/active_record/oracle_enhanced/type/integer.rb +3 -4
  28. data/lib/active_record/oracle_enhanced/type/json.rb +8 -0
  29. data/lib/active_record/oracle_enhanced/type/national_character_string.rb +1 -1
  30. data/lib/active_record/oracle_enhanced/type/raw.rb +2 -3
  31. data/lib/active_record/oracle_enhanced/type/string.rb +2 -2
  32. data/lib/active_record/oracle_enhanced/type/text.rb +2 -2
  33. data/lib/active_record/oracle_enhanced/type/timestamptz.rb +23 -0
  34. data/lib/activerecord-oracle_enhanced-adapter.rb +2 -2
  35. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +55 -162
  36. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +32 -34
  37. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +44 -42
  38. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +250 -357
  39. data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +14 -6
  40. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +3 -5
  41. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +115 -124
  42. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +2 -3
  43. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +68 -72
  44. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +64 -80
  45. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +223 -329
  46. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +18 -20
  47. data/spec/spec_config.yaml.template +11 -0
  48. data/spec/spec_helper.rb +59 -59
  49. data/spec/support/alter_system_user_password.sql +2 -0
  50. data/spec/support/create_oracle_enhanced_users.sql +31 -0
  51. metadata +25 -25
  52. data/.rspec +0 -2
  53. data/Gemfile +0 -22
  54. data/RUNNING_TESTS.md +0 -83
  55. data/Rakefile +0 -45
  56. data/activerecord-oracle_enhanced-adapter.gemspec +0 -94
  57. data/lib/active_record/connection_adapters/oracle_enhanced/cpk.rb +0 -19
  58. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
@@ -74,9 +74,9 @@ module ActiveRecord
74
74
  def add_context_index(table_name, column_name, options = {})
75
75
  self.all_schema_indexes = nil
76
76
  column_names = Array(column_name)
77
- index_name = options[:name] || index_name(table_name, :column => options[:index_column] || column_names,
77
+ index_name = options[:name] || index_name(table_name, column: options[:index_column] || column_names,
78
78
  # CONEXT index name max length is 25
79
- :identifier_max_length => 25)
79
+ identifier_max_length: 25)
80
80
 
81
81
  quoted_column_name = quote_column_name(options[:index_column] || column_names.first)
82
82
  if options[:index_column_trigger_on]
@@ -129,10 +129,10 @@ module ActiveRecord
129
129
  def remove_context_index(table_name, options = {})
130
130
  self.all_schema_indexes = nil
131
131
  unless Hash === options # if column names passed as argument
132
- options = {:column => Array(options)}
132
+ options = { column: Array(options) }
133
133
  end
134
134
  index_name = options[:name] || index_name(table_name,
135
- :column => options[:index_column] || options[:column], :identifier_max_length => 25)
135
+ column: options[:index_column] || options[:column], identifier_max_length: 25)
136
136
  execute "DROP INDEX #{index_name}"
137
137
  drop_ctx_preference(default_datastore_name(index_name))
138
138
  drop_ctx_preference(default_storage_name(index_name))
@@ -143,17 +143,17 @@ module ActiveRecord
143
143
 
144
144
  private
145
145
 
146
- def create_datastore_procedure(table_name, procedure_name, column_names, options)
147
- quoted_table_name = quote_table_name(table_name)
148
- select_queries, column_names = column_names.partition { |c| c.to_s =~ /^\s*SELECT\s+/i }
149
- select_queries = select_queries.map { |s| s.strip.gsub(/\s+/, ' ') }
150
- keys, selected_columns = parse_select_queries(select_queries)
151
- quoted_column_names = (column_names+keys).map{|col| quote_column_name(col)}
152
- execute compress_lines(<<-SQL)
146
+ def create_datastore_procedure(table_name, procedure_name, column_names, options)
147
+ quoted_table_name = quote_table_name(table_name)
148
+ select_queries, column_names = column_names.partition { |c| c.to_s =~ /^\s*SELECT\s+/i }
149
+ select_queries = select_queries.map { |s| s.strip.gsub(/\s+/, " ") }
150
+ keys, selected_columns = parse_select_queries(select_queries)
151
+ quoted_column_names = (column_names + keys).map { |col| quote_column_name(col) }
152
+ execute compress_lines(<<-SQL)
153
153
  CREATE OR REPLACE PROCEDURE #{quote_table_name(procedure_name)}
154
154
  (p_rowid IN ROWID,
155
155
  p_clob IN OUT NOCOPY CLOB) IS
156
- -- add_context_index_parameters #{(column_names+select_queries).inspect}#{!options.empty? ? ', ' << options.inspect[1..-2] : ''}
156
+ -- add_context_index_parameters #{(column_names + select_queries).inspect}#{!options.empty? ? ', ' << options.inspect[1..-2] : ''}
157
157
  #{
158
158
  selected_columns.map do |cols|
159
159
  cols.map do |col|
@@ -170,171 +170,171 @@ module ActiveRecord
170
170
  #{
171
171
  (column_names.map do |col|
172
172
  col = col.to_s
173
- "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length+2}, '<#{col}>');\n" <<
173
+ "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length + 2}, '<#{col}>');\n" <<
174
174
  "IF LENGTH(r1.#{col}) > 0 THEN\n" <<
175
175
  "DBMS_LOB.WRITEAPPEND(p_clob, LENGTH(r1.#{col}), r1.#{col});\n" <<
176
176
  "END IF;\n" <<
177
- "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length+3}, '</#{col}>');\n"
177
+ "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length + 3}, '</#{col}>');\n"
178
178
  end.join) <<
179
179
  (selected_columns.zip(select_queries).map do |cols, query|
180
180
  (cols.map do |col|
181
181
  "l_#{col} := '';\n"
182
182
  end.join) <<
183
183
  "FOR r2 IN (\n" <<
184
- query.gsub(/:(\w+)/,"r1.\\1") << "\n) LOOP\n" <<
184
+ query.gsub(/:(\w+)/, "r1.\\1") << "\n) LOOP\n" <<
185
185
  (cols.map do |col|
186
186
  "l_#{col} := l_#{col} || r2.#{col} || CHR(10);\n"
187
187
  end.join) <<
188
188
  "END LOOP;\n" <<
189
189
  (cols.map do |col|
190
190
  col = col.to_s
191
- "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length+2}, '<#{col}>');\n" <<
191
+ "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length + 2}, '<#{col}>');\n" <<
192
192
  "IF LENGTH(l_#{col}) > 0 THEN\n" <<
193
193
  "DBMS_LOB.WRITEAPPEND(p_clob, LENGTH(l_#{col}), l_#{col});\n" <<
194
194
  "END IF;\n" <<
195
- "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length+3}, '</#{col}>');\n"
195
+ "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length + 3}, '</#{col}>');\n"
196
196
  end.join)
197
197
  end.join)
198
198
  }
199
199
  END LOOP;
200
200
  END;
201
201
  SQL
202
- end
202
+ end
203
203
 
204
- def parse_select_queries(select_queries)
205
- keys = []
206
- selected_columns = []
207
- select_queries.each do |query|
208
- # get primary or foreign keys like :id or :something_id
209
- keys << (query.scan(/:\w+/).map{|k| k[1..-1].downcase.to_sym})
210
- select_part = query.scan(/^select\s.*\sfrom/i).first
211
- selected_columns << select_part.scan(/\sas\s+(\w+)/i).map{|c| c.first}
204
+ def parse_select_queries(select_queries)
205
+ keys = []
206
+ selected_columns = []
207
+ select_queries.each do |query|
208
+ # get primary or foreign keys like :id or :something_id
209
+ keys << (query.scan(/:\w+/).map { |k| k[1..-1].downcase.to_sym })
210
+ select_part = query.scan(/^select\s.*\sfrom/i).first
211
+ selected_columns << select_part.scan(/\sas\s+(\w+)/i).map { |c| c.first }
212
+ end
213
+ [keys.flatten.uniq, selected_columns]
212
214
  end
213
- [keys.flatten.uniq, selected_columns]
214
- end
215
215
 
216
- def create_datastore_preference(datastore_name, procedure_name)
217
- drop_ctx_preference(datastore_name)
218
- execute <<-SQL
216
+ def create_datastore_preference(datastore_name, procedure_name)
217
+ drop_ctx_preference(datastore_name)
218
+ execute <<-SQL
219
219
  BEGIN
220
220
  CTX_DDL.CREATE_PREFERENCE('#{datastore_name}', 'USER_DATASTORE');
221
221
  CTX_DDL.SET_ATTRIBUTE('#{datastore_name}', 'PROCEDURE', '#{procedure_name}');
222
222
  END;
223
223
  SQL
224
- end
224
+ end
225
225
 
226
- def create_storage_preference(storage_name, tablespace)
227
- drop_ctx_preference(storage_name)
228
- sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{storage_name}', 'BASIC_STORAGE');\n"
229
- ['I_TABLE_CLAUSE', 'K_TABLE_CLAUSE', 'R_TABLE_CLAUSE',
230
- 'N_TABLE_CLAUSE', 'I_INDEX_CLAUSE', 'P_TABLE_CLAUSE'].each do |clause|
231
- default_clause = case clause
232
- when 'R_TABLE_CLAUSE'; 'LOB(DATA) STORE AS (CACHE) '
233
- when 'I_INDEX_CLAUSE'; 'COMPRESS 2 '
234
- else ''
226
+ def create_storage_preference(storage_name, tablespace)
227
+ drop_ctx_preference(storage_name)
228
+ sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{storage_name}', 'BASIC_STORAGE');\n"
229
+ ["I_TABLE_CLAUSE", "K_TABLE_CLAUSE", "R_TABLE_CLAUSE",
230
+ "N_TABLE_CLAUSE", "I_INDEX_CLAUSE", "P_TABLE_CLAUSE"].each do |clause|
231
+ default_clause = case clause
232
+ when "R_TABLE_CLAUSE"; "LOB(DATA) STORE AS (CACHE) "
233
+ when "I_INDEX_CLAUSE"; "COMPRESS 2 "
234
+ else ""
235
+ end
236
+ sql << "CTX_DDL.SET_ATTRIBUTE('#{storage_name}', '#{clause}', '#{default_clause}TABLESPACE #{tablespace}');\n"
235
237
  end
236
- sql << "CTX_DDL.SET_ATTRIBUTE('#{storage_name}', '#{clause}', '#{default_clause}TABLESPACE #{tablespace}');\n"
238
+ sql << "END;\n"
239
+ execute sql
237
240
  end
238
- sql << "END;\n"
239
- execute sql
240
- end
241
241
 
242
- def create_lexer_preference(lexer_name, lexer_type, options)
243
- drop_ctx_preference(lexer_name)
244
- sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{lexer_name}', '#{lexer_type}');\n"
245
- options.each do |key, value|
246
- plsql_value = case value
247
- when String; "'#{value}'"
248
- when true; "'YES'"
249
- when false; "'NO'"
250
- when nil; 'NULL'
251
- else value
242
+ def create_lexer_preference(lexer_name, lexer_type, options)
243
+ drop_ctx_preference(lexer_name)
244
+ sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{lexer_name}', '#{lexer_type}');\n"
245
+ options.each do |key, value|
246
+ plsql_value = case value
247
+ when String; "'#{value}'"
248
+ when true; "'YES'"
249
+ when false; "'NO'"
250
+ when nil; "NULL"
251
+ else value
252
+ end
253
+ sql << "CTX_DDL.SET_ATTRIBUTE('#{lexer_name}', '#{key}', #{plsql_value});\n"
252
254
  end
253
- sql << "CTX_DDL.SET_ATTRIBUTE('#{lexer_name}', '#{key}', #{plsql_value});\n"
255
+ sql << "END;\n"
256
+ execute sql
254
257
  end
255
- sql << "END;\n"
256
- execute sql
257
- end
258
258
 
259
- def create_wordlist_preference(wordlist_name, wordlist_type, options)
260
- drop_ctx_preference(wordlist_name)
261
- sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{wordlist_name}', '#{wordlist_type}');\n"
262
- options.each do |key, value|
263
- plsql_value = case value
264
- when String; "'#{value}'"
265
- when true; "'YES'"
266
- when false; "'NO'"
267
- when nil; 'NULL'
268
- else value
259
+ def create_wordlist_preference(wordlist_name, wordlist_type, options)
260
+ drop_ctx_preference(wordlist_name)
261
+ sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{wordlist_name}', '#{wordlist_type}');\n"
262
+ options.each do |key, value|
263
+ plsql_value = case value
264
+ when String; "'#{value}'"
265
+ when true; "'YES'"
266
+ when false; "'NO'"
267
+ when nil; "NULL"
268
+ else value
269
+ end
270
+ sql << "CTX_DDL.SET_ATTRIBUTE('#{wordlist_name}', '#{key}', #{plsql_value});\n"
269
271
  end
270
- sql << "CTX_DDL.SET_ATTRIBUTE('#{wordlist_name}', '#{key}', #{plsql_value});\n"
272
+ sql << "END;\n"
273
+ execute sql
271
274
  end
272
- sql << "END;\n"
273
- execute sql
274
- end
275
275
 
276
- def drop_ctx_preference(preference_name)
277
- execute "BEGIN CTX_DDL.DROP_PREFERENCE('#{preference_name}'); END;" rescue nil
278
- end
276
+ def drop_ctx_preference(preference_name)
277
+ execute "BEGIN CTX_DDL.DROP_PREFERENCE('#{preference_name}'); END;" rescue nil
278
+ end
279
279
 
280
- def create_index_column_trigger(table_name, index_name, index_column, index_column_source)
281
- trigger_name = default_index_column_trigger_name(index_name)
282
- columns = Array(index_column_source)
283
- quoted_column_names = columns.map{|col| quote_column_name(col)}.join(', ')
284
- execute compress_lines(<<-SQL)
280
+ def create_index_column_trigger(table_name, index_name, index_column, index_column_source)
281
+ trigger_name = default_index_column_trigger_name(index_name)
282
+ columns = Array(index_column_source)
283
+ quoted_column_names = columns.map { |col| quote_column_name(col) }.join(", ")
284
+ execute compress_lines(<<-SQL)
285
285
  CREATE OR REPLACE TRIGGER #{quote_table_name(trigger_name)}
286
286
  BEFORE UPDATE OF #{quoted_column_names} ON #{quote_table_name(table_name)} FOR EACH ROW
287
287
  BEGIN
288
288
  :new.#{quote_column_name(index_column)} := '1';
289
289
  END;
290
290
  SQL
291
- end
291
+ end
292
292
 
293
- def drop_index_column_trigger(index_name)
294
- trigger_name = default_index_column_trigger_name(index_name)
295
- execute "DROP TRIGGER #{quote_table_name(trigger_name)}" rescue nil
296
- end
293
+ def drop_index_column_trigger(index_name)
294
+ trigger_name = default_index_column_trigger_name(index_name)
295
+ execute "DROP TRIGGER #{quote_table_name(trigger_name)}" rescue nil
296
+ end
297
297
 
298
- def default_datastore_procedure(index_name)
299
- "#{index_name}_prc"
300
- end
298
+ def default_datastore_procedure(index_name)
299
+ "#{index_name}_prc"
300
+ end
301
301
 
302
- def default_datastore_name(index_name)
303
- "#{index_name}_dst"
304
- end
302
+ def default_datastore_name(index_name)
303
+ "#{index_name}_dst"
304
+ end
305
305
 
306
- def default_storage_name(index_name)
307
- "#{index_name}_sto"
308
- end
306
+ def default_storage_name(index_name)
307
+ "#{index_name}_sto"
308
+ end
309
309
 
310
- def default_index_column_trigger_name(index_name)
311
- "#{index_name}_trg"
312
- end
310
+ def default_index_column_trigger_name(index_name)
311
+ "#{index_name}_trg"
312
+ end
313
313
 
314
- def default_lexer_name(index_name)
315
- "#{index_name}_lex"
316
- end
314
+ def default_lexer_name(index_name)
315
+ "#{index_name}_lex"
316
+ end
317
317
 
318
- def default_wordlist_name(index_name)
319
- "#{index_name}_wl"
320
- end
318
+ def default_wordlist_name(index_name)
319
+ "#{index_name}_wl"
320
+ end
321
321
 
322
- module BaseClassMethods
323
- # Declare that model table has context index defined.
324
- # As a result <tt>contains</tt> class scope method is defined.
325
- def has_context_index
326
- extend ContextIndexClassMethods
322
+ module BaseClassMethods
323
+ # Declare that model table has context index defined.
324
+ # As a result <tt>contains</tt> class scope method is defined.
325
+ def has_context_index
326
+ extend ContextIndexClassMethods
327
+ end
327
328
  end
328
- end
329
329
 
330
- module ContextIndexClassMethods
331
- # Add context index condition.
332
- def contains(column, query, options ={})
333
- score_label = options[:label].to_i || 1
334
- where("CONTAINS(#{connection.quote_table_name(column)}, ?, #{score_label}) > 0", query).
335
- order("SCORE(#{score_label}) DESC")
330
+ module ContextIndexClassMethods
331
+ # Add context index condition.
332
+ def contains(column, query, options = {})
333
+ score_label = options[:label].to_i || 1
334
+ where("CONTAINS(#{connection.quote_table_name(column)}, ?, #{score_label}) > 0", query).
335
+ order("SCORE(#{score_label}) DESC")
336
+ end
336
337
  end
337
- end
338
338
  end
339
339
  end
340
340
  end
@@ -16,10 +16,10 @@ module ActiveRecord
16
16
  reload_type_map
17
17
  end
18
18
 
19
- def exec_query(sql, name = 'SQL', binds = [], prepare: false)
20
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
19
+ def exec_query(sql, name = "SQL", binds = [], prepare: false)
20
+ type_casted_binds = type_casted_binds(binds)
21
21
 
22
- log(sql, name, binds) do
22
+ log(sql, name, binds, type_casted_binds) do
23
23
  cursor = nil
24
24
  cached = false
25
25
  if without_prepared_statement?(binds)
@@ -38,14 +38,14 @@ module ActiveRecord
38
38
 
39
39
  cursor.exec
40
40
 
41
- if name == 'EXPLAIN' and sql =~ /^EXPLAIN/
41
+ if (name == "EXPLAIN") && sql =~ /^EXPLAIN/
42
42
  res = true
43
43
  else
44
44
  columns = cursor.get_col_names.map do |col_name|
45
45
  @connection.oracle_downcase(col_name)
46
46
  end
47
47
  rows = []
48
- fetch_options = {:get_lob_value => (name != 'Writable Large Object')}
48
+ fetch_options = { get_lob_value: (name != "Writable Large Object") }
49
49
  while row = cursor.fetch(fetch_options)
50
50
  rows << row
51
51
  end
@@ -69,34 +69,35 @@ module ActiveRecord
69
69
  sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
70
70
  return if sql =~ /FROM all_/
71
71
  if ORACLE_ENHANCED_CONNECTION == :jdbc
72
- exec_query(sql, 'EXPLAIN', binds)
72
+ exec_query(sql, "EXPLAIN", binds)
73
73
  else
74
- exec_query(sql, 'EXPLAIN')
74
+ exec_query(sql, "EXPLAIN")
75
75
  end
76
- select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", 'EXPLAIN').join("\n")
77
- end
78
-
79
- # Returns an array of arrays containing the field values.
80
- # Order is the same as that returned by #columns.
81
- def select_rows(sql, name = nil, binds = [])
82
- exec_query(sql, name, binds).rows
76
+ select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", "EXPLAIN").join("\n")
83
77
  end
84
78
 
85
79
  # New method in ActiveRecord 3.1
86
80
  # Will add RETURNING clause in case of trigger generated primary keys
87
81
  def sql_for_insert(sql, pk, id_value, sequence_name, binds)
88
- unless id_value || pk == false || pk.nil? || (defined?(CompositePrimaryKeys) && pk.kind_of?(CompositePrimaryKeys::CompositeKeys))
82
+ unless id_value || pk == false || pk.nil? || pk.is_a?(Array)
89
83
  sql = "#{sql} RETURNING #{quote_column_name(pk)} INTO :returning_id"
90
84
  (binds = binds.dup) << ActiveRecord::Relation::QueryAttribute.new("returning_id", nil, ActiveRecord::OracleEnhanced::Type::Integer.new)
91
85
  end
92
86
  super
93
87
  end
94
88
 
89
+ def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
90
+ pk = nil if id_value
91
+ super
92
+ end
93
+
95
94
  # New method in ActiveRecord 3.1
96
- def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
97
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
95
+ def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
96
+ sql, binds = sql_for_insert(sql, pk, nil, sequence_name, binds)
97
+ type_casted_binds = type_casted_binds(binds)
98
98
 
99
- log(sql, name, binds) do
99
+ log(sql, name, binds, type_casted_binds) do
100
+ cached = false
100
101
  returning_id_col = returning_id_index = nil
101
102
  if without_prepared_statement?(binds)
102
103
  cursor = @connection.prepare(sql)
@@ -115,6 +116,7 @@ module ActiveRecord
115
116
  cursor.bind_returning_param(returning_id_index, Integer) if ORACLE_ENHANCED_CONNECTION == :jdbc
116
117
  end
117
118
 
119
+ cached = true
118
120
  end
119
121
 
120
122
  cursor.exec_update
@@ -124,24 +126,25 @@ module ActiveRecord
124
126
  returning_id = cursor.get_returning_param(returning_id_index, Integer).to_i
125
127
  rows << [returning_id]
126
128
  end
129
+ cursor.close unless cached
127
130
  ActiveRecord::Result.new(returning_id_col || [], rows)
128
131
  end
129
132
  end
130
133
 
131
134
  # New method in ActiveRecord 3.1
132
- def exec_update(sql, name, binds)
133
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
135
+ def exec_update(sql, name = nil, binds = [])
136
+ type_casted_binds = type_casted_binds(binds)
134
137
 
135
- log(sql, name, binds) do
138
+ log(sql, name, binds, type_casted_binds) do
136
139
  cached = false
137
140
  if without_prepared_statement?(binds)
138
141
  cursor = @connection.prepare(sql)
139
142
  else
140
- cursor = if @statements.key?(sql)
141
- @statements[sql]
142
- else
143
- @statements[sql] = @connection.prepare(sql)
144
- end
143
+ if @statements.key?(sql)
144
+ cursor = @statements[sql]
145
+ else
146
+ cursor = @statements[sql] = @connection.prepare(sql)
147
+ end
145
148
 
146
149
  cursor.bind_params(type_casted_binds)
147
150
 
@@ -202,7 +205,7 @@ module ActiveRecord
202
205
  # Returns default sequence name for table.
203
206
  # Will take all or first 26 characters of table name and append _seq suffix
204
207
  def default_sequence_name(table_name, primary_key = nil)
205
- table_name.to_s.gsub((/(^|\.)([\w$-]{1,#{sequence_name_length-4}})([\w$-]*)$/), '\1\2_seq')
208
+ table_name.to_s.gsub((/(^|\.)([\w$-]{1,#{sequence_name_length - 4}})([\w$-]*)$/), '\1\2_seq')
206
209
  end
207
210
 
208
211
  # Inserts the given fixture into the table. Overridden to properly handle lobs.
@@ -220,6 +223,13 @@ module ActiveRecord
220
223
  write_lobs(table_name, klass, fixture, klass.lob_columns)
221
224
  end
222
225
  end
226
+
227
+ # Oracle Database does not support this feature
228
+ # Refer https://community.oracle.com/ideas/13845 and consider to vote
229
+ # if you need this feature.
230
+ def empty_insert_statement_value
231
+ raise NotImplementedError
232
+ end
223
233
  end
224
234
  end
225
235
  end
@@ -1,21 +1,21 @@
1
- require 'active_record/base'
1
+ require "active_record/base"
2
2
 
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  class OracleEnhancedAdapter
6
6
  class DatabaseTasks
7
- delegate :connection, :establish_connection, :to => ActiveRecord::Base
7
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
8
8
 
9
9
  def initialize(config)
10
10
  @config = config
11
11
  end
12
12
 
13
13
  def create
14
- system_password = ENV.fetch('ORACLE_SYSTEM_PASSWORD') {
14
+ system_password = ENV.fetch("ORACLE_SYSTEM_PASSWORD") {
15
15
  print "Please provide the SYSTEM password for your Oracle installation (set ORACLE_SYSTEM_PASSWORD to avoid this prompt)\n>"
16
16
  $stdin.gets.strip
17
17
  }
18
- establish_connection(@config.merge('username' => 'SYSTEM', 'password' => system_password))
18
+ establish_connection(@config.merge("username" => "SYSTEM", "password" => system_password))
19
19
  begin
20
20
  connection.execute "CREATE USER #{@config['username']} IDENTIFIED BY #{@config['password']}"
21
21
  rescue => e
@@ -39,18 +39,18 @@ module ActiveRecord
39
39
 
40
40
  def purge
41
41
  drop
42
- connection.execute('PURGE RECYCLEBIN') rescue nil
42
+ connection.execute("PURGE RECYCLEBIN") rescue nil
43
43
  end
44
44
 
45
- def structure_dump(filename)
45
+ def structure_dump(filename, extra_flags)
46
46
  establish_connection(@config)
47
- File.open(filename, 'w:utf-8') { |f| f << connection.structure_dump }
48
- if @config['structure_dump'] == 'db_stored_code'
49
- File.open(filename, 'a') { |f| f << connection.structure_dump_db_stored_code }
47
+ File.open(filename, "w:utf-8") { |f| f << connection.structure_dump }
48
+ if @config["structure_dump"] == "db_stored_code"
49
+ File.open(filename, "a") { |f| f << connection.structure_dump_db_stored_code }
50
50
  end
51
51
  end
52
52
 
53
- def structure_load(filename)
53
+ def structure_load(filename, extra_flags)
54
54
  establish_connection(@config)
55
55
  connection.execute_structure_dump(File.read(filename))
56
56
  end