activerecord-oracle_enhanced-adapter 1.7.11 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
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