activerecord-oracle_enhanced-adapter 1.7.3 → 1.8.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +288 -0
  3. data/README.md +44 -0
  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 -63
  7. data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +6 -52
  8. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +13 -16
  9. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +117 -119
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +33 -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 +59 -77
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +0 -4
  14. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +56 -82
  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 +77 -77
  17. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +16 -45
  18. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +60 -65
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +33 -51
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +149 -162
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +119 -122
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +3 -4
  23. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +69 -107
  24. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -1
  25. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +315 -538
  26. data/lib/active_record/oracle_enhanced/type/boolean.rb +7 -11
  27. data/lib/active_record/oracle_enhanced/type/integer.rb +4 -5
  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 -2
  30. data/lib/active_record/oracle_enhanced/type/raw.rb +2 -4
  31. data/lib/active_record/oracle_enhanced/type/string.rb +2 -3
  32. data/lib/active_record/oracle_enhanced/type/text.rb +2 -4
  33. data/lib/active_record/oracle_enhanced/type/timestamptz.rb +23 -0
  34. data/lib/activerecord-oracle_enhanced-adapter.rb +14 -13
  35. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +129 -166
  36. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +50 -33
  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 +283 -378
  39. data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +14 -7
  40. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +5 -7
  41. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +118 -127
  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 +74 -78
  44. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +68 -83
  45. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +308 -321
  46. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +103 -48
  47. data/spec/spec_config.yaml.template +11 -0
  48. data/spec/spec_helper.rb +59 -60
  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 -50
  55. data/Rakefile +0 -45
  56. data/activerecord-oracle_enhanced-adapter.gemspec +0 -95
  57. data/lib/active_record/connection_adapters/oracle_enhanced/cpk.rb +0 -21
  58. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
@@ -2,7 +2,6 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module OracleEnhanced
4
4
  module ContextIndex
5
-
6
5
  # Define full text index with Oracle specific CONTEXT index type
7
6
  #
8
7
  # Oracle CONTEXT index by default supports full text indexing of one column.
@@ -75,9 +74,9 @@ module ActiveRecord
75
74
  def add_context_index(table_name, column_name, options = {})
76
75
  self.all_schema_indexes = nil
77
76
  column_names = Array(column_name)
78
- 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,
79
78
  # CONEXT index name max length is 25
80
- :identifier_max_length => 25)
79
+ identifier_max_length: 25)
81
80
 
82
81
  quoted_column_name = quote_column_name(options[:index_column] || column_names.first)
83
82
  if options[:index_column_trigger_on]
@@ -130,10 +129,10 @@ module ActiveRecord
130
129
  def remove_context_index(table_name, options = {})
131
130
  self.all_schema_indexes = nil
132
131
  unless Hash === options # if column names passed as argument
133
- options = {:column => Array(options)}
132
+ options = { column: Array(options) }
134
133
  end
135
134
  index_name = options[:name] || index_name(table_name,
136
- :column => options[:index_column] || options[:column], :identifier_max_length => 25)
135
+ column: options[:index_column] || options[:column], identifier_max_length: 25)
137
136
  execute "DROP INDEX #{index_name}"
138
137
  drop_ctx_preference(default_datastore_name(index_name))
139
138
  drop_ctx_preference(default_storage_name(index_name))
@@ -144,17 +143,17 @@ module ActiveRecord
144
143
 
145
144
  private
146
145
 
147
- def create_datastore_procedure(table_name, procedure_name, column_names, options)
148
- quoted_table_name = quote_table_name(table_name)
149
- select_queries, column_names = column_names.partition { |c| c.to_s =~ /^\s*SELECT\s+/i }
150
- select_queries = select_queries.map { |s| s.strip.gsub(/\s+/, ' ') }
151
- keys, selected_columns = parse_select_queries(select_queries)
152
- quoted_column_names = (column_names+keys).map{|col| quote_column_name(col)}
153
- 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)
154
153
  CREATE OR REPLACE PROCEDURE #{quote_table_name(procedure_name)}
155
154
  (p_rowid IN ROWID,
156
155
  p_clob IN OUT NOCOPY CLOB) IS
157
- -- 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] : ''}
158
157
  #{
159
158
  selected_columns.map do |cols|
160
159
  cols.map do |col|
@@ -171,172 +170,171 @@ module ActiveRecord
171
170
  #{
172
171
  (column_names.map do |col|
173
172
  col = col.to_s
174
- "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length+2}, '<#{col}>');\n" <<
173
+ "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length + 2}, '<#{col}>');\n" <<
175
174
  "IF LENGTH(r1.#{col}) > 0 THEN\n" <<
176
175
  "DBMS_LOB.WRITEAPPEND(p_clob, LENGTH(r1.#{col}), r1.#{col});\n" <<
177
176
  "END IF;\n" <<
178
- "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length+3}, '</#{col}>');\n"
177
+ "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length + 3}, '</#{col}>');\n"
179
178
  end.join) <<
180
179
  (selected_columns.zip(select_queries).map do |cols, query|
181
180
  (cols.map do |col|
182
181
  "l_#{col} := '';\n"
183
182
  end.join) <<
184
183
  "FOR r2 IN (\n" <<
185
- query.gsub(/:(\w+)/,"r1.\\1") << "\n) LOOP\n" <<
184
+ query.gsub(/:(\w+)/, "r1.\\1") << "\n) LOOP\n" <<
186
185
  (cols.map do |col|
187
186
  "l_#{col} := l_#{col} || r2.#{col} || CHR(10);\n"
188
187
  end.join) <<
189
188
  "END LOOP;\n" <<
190
189
  (cols.map do |col|
191
190
  col = col.to_s
192
- "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length+2}, '<#{col}>');\n" <<
191
+ "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length + 2}, '<#{col}>');\n" <<
193
192
  "IF LENGTH(l_#{col}) > 0 THEN\n" <<
194
193
  "DBMS_LOB.WRITEAPPEND(p_clob, LENGTH(l_#{col}), l_#{col});\n" <<
195
194
  "END IF;\n" <<
196
- "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length+3}, '</#{col}>');\n"
195
+ "DBMS_LOB.WRITEAPPEND(p_clob, #{col.length + 3}, '</#{col}>');\n"
197
196
  end.join)
198
197
  end.join)
199
198
  }
200
199
  END LOOP;
201
200
  END;
202
201
  SQL
203
- end
202
+ end
204
203
 
205
- def parse_select_queries(select_queries)
206
- keys = []
207
- selected_columns = []
208
- select_queries.each do |query|
209
- # get primary or foreign keys like :id or :something_id
210
- keys << (query.scan(/:\w+/).map{|k| k[1..-1].downcase.to_sym})
211
- select_part = query.scan(/^select\s.*\sfrom/i).first
212
- 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]
213
214
  end
214
- [keys.flatten.uniq, selected_columns]
215
- end
216
215
 
217
- def create_datastore_preference(datastore_name, procedure_name)
218
- drop_ctx_preference(datastore_name)
219
- execute <<-SQL
216
+ def create_datastore_preference(datastore_name, procedure_name)
217
+ drop_ctx_preference(datastore_name)
218
+ execute <<-SQL
220
219
  BEGIN
221
220
  CTX_DDL.CREATE_PREFERENCE('#{datastore_name}', 'USER_DATASTORE');
222
221
  CTX_DDL.SET_ATTRIBUTE('#{datastore_name}', 'PROCEDURE', '#{procedure_name}');
223
222
  END;
224
223
  SQL
225
- end
224
+ end
226
225
 
227
- def create_storage_preference(storage_name, tablespace)
228
- drop_ctx_preference(storage_name)
229
- sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{storage_name}', 'BASIC_STORAGE');\n"
230
- ['I_TABLE_CLAUSE', 'K_TABLE_CLAUSE', 'R_TABLE_CLAUSE',
231
- 'N_TABLE_CLAUSE', 'I_INDEX_CLAUSE', 'P_TABLE_CLAUSE'].each do |clause|
232
- default_clause = case clause
233
- when 'R_TABLE_CLAUSE'; 'LOB(DATA) STORE AS (CACHE) '
234
- when 'I_INDEX_CLAUSE'; 'COMPRESS 2 '
235
- 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"
236
237
  end
237
- sql << "CTX_DDL.SET_ATTRIBUTE('#{storage_name}', '#{clause}', '#{default_clause}TABLESPACE #{tablespace}');\n"
238
+ sql << "END;\n"
239
+ execute sql
238
240
  end
239
- sql << "END;\n"
240
- execute sql
241
- end
242
241
 
243
- def create_lexer_preference(lexer_name, lexer_type, options)
244
- drop_ctx_preference(lexer_name)
245
- sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{lexer_name}', '#{lexer_type}');\n"
246
- options.each do |key, value|
247
- plsql_value = case value
248
- when String; "'#{value}'"
249
- when true; "'YES'"
250
- when false; "'NO'"
251
- when nil; 'NULL'
252
- 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"
253
254
  end
254
- sql << "CTX_DDL.SET_ATTRIBUTE('#{lexer_name}', '#{key}', #{plsql_value});\n"
255
+ sql << "END;\n"
256
+ execute sql
255
257
  end
256
- sql << "END;\n"
257
- execute sql
258
- end
259
258
 
260
- def create_wordlist_preference(wordlist_name, wordlist_type, options)
261
- drop_ctx_preference(wordlist_name)
262
- sql = "BEGIN\nCTX_DDL.CREATE_PREFERENCE('#{wordlist_name}', '#{wordlist_type}');\n"
263
- options.each do |key, value|
264
- plsql_value = case value
265
- when String; "'#{value}'"
266
- when true; "'YES'"
267
- when false; "'NO'"
268
- when nil; 'NULL'
269
- 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"
270
271
  end
271
- sql << "CTX_DDL.SET_ATTRIBUTE('#{wordlist_name}', '#{key}', #{plsql_value});\n"
272
+ sql << "END;\n"
273
+ execute sql
272
274
  end
273
- sql << "END;\n"
274
- execute sql
275
- end
276
275
 
277
- def drop_ctx_preference(preference_name)
278
- execute "BEGIN CTX_DDL.DROP_PREFERENCE('#{preference_name}'); END;" rescue nil
279
- end
276
+ def drop_ctx_preference(preference_name)
277
+ execute "BEGIN CTX_DDL.DROP_PREFERENCE('#{preference_name}'); END;" rescue nil
278
+ end
280
279
 
281
- def create_index_column_trigger(table_name, index_name, index_column, index_column_source)
282
- trigger_name = default_index_column_trigger_name(index_name)
283
- columns = Array(index_column_source)
284
- quoted_column_names = columns.map{|col| quote_column_name(col)}.join(', ')
285
- 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)
286
285
  CREATE OR REPLACE TRIGGER #{quote_table_name(trigger_name)}
287
286
  BEFORE UPDATE OF #{quoted_column_names} ON #{quote_table_name(table_name)} FOR EACH ROW
288
287
  BEGIN
289
288
  :new.#{quote_column_name(index_column)} := '1';
290
289
  END;
291
290
  SQL
292
- end
293
-
294
- def drop_index_column_trigger(index_name)
295
- trigger_name = default_index_column_trigger_name(index_name)
296
- execute "DROP TRIGGER #{quote_table_name(trigger_name)}" rescue nil
297
- end
291
+ end
298
292
 
299
- def default_datastore_procedure(index_name)
300
- "#{index_name}_prc"
301
- 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
302
297
 
303
- def default_datastore_name(index_name)
304
- "#{index_name}_dst"
305
- end
298
+ def default_datastore_procedure(index_name)
299
+ "#{index_name}_prc"
300
+ end
306
301
 
307
- def default_storage_name(index_name)
308
- "#{index_name}_sto"
309
- end
302
+ def default_datastore_name(index_name)
303
+ "#{index_name}_dst"
304
+ end
310
305
 
311
- def default_index_column_trigger_name(index_name)
312
- "#{index_name}_trg"
313
- end
306
+ def default_storage_name(index_name)
307
+ "#{index_name}_sto"
308
+ end
314
309
 
315
- def default_lexer_name(index_name)
316
- "#{index_name}_lex"
317
- end
310
+ def default_index_column_trigger_name(index_name)
311
+ "#{index_name}_trg"
312
+ end
318
313
 
319
- def default_wordlist_name(index_name)
320
- "#{index_name}_wl"
321
- end
314
+ def default_lexer_name(index_name)
315
+ "#{index_name}_lex"
316
+ end
322
317
 
323
- module BaseClassMethods
324
- # Declare that model table has context index defined.
325
- # As a result <tt>contains</tt> class scope method is defined.
326
- def has_context_index
327
- extend ContextIndexClassMethods
318
+ def default_wordlist_name(index_name)
319
+ "#{index_name}_wl"
328
320
  end
329
- end
330
321
 
331
- module ContextIndexClassMethods
332
- # Add context index condition.
333
- def contains(column, query, options ={})
334
- score_label = options[:label].to_i || 1
335
- where("CONTAINS(#{connection.quote_table_name(column)}, ?, #{score_label}) > 0", query).
336
- order("SCORE(#{score_label}) DESC")
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
337
328
  end
338
- end
339
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")
336
+ end
337
+ end
340
338
  end
341
339
  end
342
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,34 @@ 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
100
  returning_id_col = returning_id_index = nil
101
101
  if without_prepared_statement?(binds)
102
102
  cursor = @connection.prepare(sql)
@@ -129,19 +129,19 @@ module ActiveRecord
129
129
  end
130
130
 
131
131
  # 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) }
132
+ def exec_update(sql, name = nil, binds = [])
133
+ type_casted_binds = type_casted_binds(binds)
134
134
 
135
- log(sql, name, binds) do
135
+ log(sql, name, binds, type_casted_binds) do
136
136
  cached = false
137
137
  if without_prepared_statement?(binds)
138
138
  cursor = @connection.prepare(sql)
139
139
  else
140
- cursor = if @statements.key?(sql)
141
- @statements[sql]
142
- else
143
- @statements[sql] = @connection.prepare(sql)
144
- end
140
+ if @statements.key?(sql)
141
+ cursor = @statements[sql]
142
+ else
143
+ cursor = @statements[sql] = @connection.prepare(sql)
144
+ end
145
145
 
146
146
  cursor.bind_params(type_casted_binds)
147
147
 
@@ -202,7 +202,7 @@ module ActiveRecord
202
202
  # Returns default sequence name for table.
203
203
  # Will take all or first 26 characters of table name and append _seq suffix
204
204
  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')
205
+ table_name.to_s.gsub((/(^|\.)([\w$-]{1,#{sequence_name_length - 4}})([\w$-]*)$/), '\1\2_seq')
206
206
  end
207
207
 
208
208
  # Inserts the given fixture into the table. Overridden to properly handle lobs.
@@ -221,6 +221,12 @@ module ActiveRecord
221
221
  end
222
222
  end
223
223
 
224
+ # Oracle Database does not support this feature
225
+ # Refer https://community.oracle.com/ideas/13845 and consider to vote
226
+ # if you need this feature.
227
+ def empty_insert_statement_value
228
+ raise NotImplementedError
229
+ end
224
230
  end
225
231
  end
226
232
  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