activerecord-oracle_enhanced-adapter 1.4.1 → 1.4.2.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. data/Gemfile +1 -0
  2. data/History.md +16 -1
  3. data/README.md +60 -35
  4. data/Rakefile +14 -1
  5. data/VERSION +1 -1
  6. data/activerecord-oracle_enhanced-adapter.gemspec +2 -2
  7. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +27 -9
  8. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +13 -1
  9. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +7 -2
  10. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +31 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +6 -1
  12. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +17 -5
  13. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +2 -1
  14. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +29 -11
  15. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +9 -4
  16. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +31 -7
  17. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +5 -1
  18. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +34 -5
  19. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +22 -0
  20. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +1 -0
  21. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +52 -6
  22. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +20 -0
  23. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +6 -2
  24. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +79 -21
  25. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +203 -35
  26. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +17 -1
  27. data/spec/spec_helper.rb +3 -1
  28. metadata +74 -51
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source 'http://rubygems.org'
3
3
  group :development do
4
4
  gem 'jeweler', '~> 1.5.1'
5
5
  gem 'rspec', '~> 2.4'
6
+ gem 'rdoc'
6
7
 
7
8
  if ENV['RAILS_GEM_VERSION']
8
9
  gem 'activerecord', "=#{ENV['RAILS_GEM_VERSION']}"
data/History.md CHANGED
@@ -1,4 +1,19 @@
1
- ### 1.4.1 / 2011-01-27
1
+ ### 1.4.2.rc1 / 2012-11-13
2
+
3
+ * Enhancements:
4
+ * Wordlist option for context index [#154]
5
+ * Fall back to directly connecting via OracleDriver on JRuby [#163]
6
+ * Allow slash-prefixed database name in database.yml for using a service [#201]
7
+ * Bug fixes:
8
+ * Fixed explain plans to work with JDBC and OCI8 [#146]
9
+ * Fixed various issues with virtual columns [#159]
10
+ * Fixed SQL structure dump with function indexes [#161]
11
+ * Fixed broken column remove inside a change_table block [#216]
12
+ * Dump indexes on virtual columns using the column's name instead of the column expression [#211]
13
+ * Don't update lobs that haven't changed or are attr_readonly [#212]
14
+ * Support dirty tracking with rails 3.2.9
15
+
16
+ ### 1.4.1 / 2012-01-27
2
17
 
3
18
  * Enhancements:
4
19
  * Support for Rails 3.2
data/README.md CHANGED
@@ -25,7 +25,7 @@ If you would like to use latest adapter version from github then specify
25
25
 
26
26
  If you are using MRI 1.8 or 1.9 Ruby implementation then you need to install ruby-oci8 gem as well as Oracle client, e.g. [Oracle Instant Client](http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html). Include in Gemfile also ruby-oci8:
27
27
 
28
- gem 'ruby-oci8', '~> 2.0.6'
28
+ gem 'ruby-oci8', '~> 2.1.0'
29
29
 
30
30
  If you are using JRuby then you need to download latest [Oracle JDBC driver](http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html) - either ojdbc6.jar for Java 6 or ojdbc5.jar for Java 5. And copy this file to one of these locations:
31
31
 
@@ -72,6 +72,15 @@ In Rails application `config/database.yml` use oracle_enhanced as adapter name,
72
72
  username: user
73
73
  password: secret
74
74
 
75
+ If you're connecting to a service name, indicate the service with a
76
+ leading slash on the database parameter:
77
+
78
+ development:
79
+ adapter: oracle_enhanced
80
+ database: /xe
81
+ username: user
82
+ password: secret
83
+
75
84
  If `TNS_ADMIN` environment variable is pointing to directory where `tnsnames.ora` file is located then you can use TNS connection name in `database` parameter. Otherwise you can directly specify database host, port (defaults to 1521) and database name in the following way:
76
85
 
77
86
  development:
@@ -248,6 +257,54 @@ And you can even create index on multiple tables by providing SELECT statements
248
257
  Post.contains(:all_text, "aaa within title")
249
258
  Post.contains(:all_text, "bbb within comment_author")
250
259
 
260
+ ### Oracle virtual collumns support
261
+
262
+ Since version R11G1 Oracle database allows adding computed [Virtual Columns](http://www.oracle-base.com/articles/11g/virtual-columns-11gr1.php) to the table.
263
+ They can be used as normal fields in the queries, in the foreign key contstraints and to partitioning data.
264
+
265
+ To define virtual column you can use `virtual` method in the `create_table` block, providing column expression in the `:as` option:
266
+
267
+ create_table :mytable do |t|
268
+ t.decimal :price, :precision => 15, :scale => 2
269
+ t.decimal :quantity, :precision => 15, :scale => 2
270
+ t.virtual :amount, :as => 'price * quantity'
271
+ end
272
+
273
+ Oracle tries to predict type of the virtual column, based on its expression but sometimes it is necessary to state type explicitly.
274
+ This can be done by providing `:type` option to the `virtual` method:
275
+
276
+ ...
277
+ t.virtual :amount_2, :as => 'ROUND(price * quantity,2)', :type => :decimal, :precision => 15, :scale => 2
278
+ t.virtual :amount_str, :as => "TO_CHAR(quantity) || ' x ' || TO_CHAR(price) || ' USD = ' || TO_CHAR(quantity*price) || ' USD'",
279
+ :type => :string, :limit => 100
280
+ ...
281
+
282
+ It is possible to add virtual column to existing table:
283
+
284
+ add_column :mytable, :amount_4, :virtual, :as => 'ROUND(price * quantity,4)', :precision => 38, :scale => 4
285
+
286
+ You can use the same options here as in the `create_table` `virtual` method.
287
+
288
+ Changing virtual columns is also possible:
289
+
290
+ change_column :mytable, :amount, :virtual, :as => 'ROUND(price * quantity,0)', :type => :integer
291
+
292
+ Virtual columns allowed in the foreign key constraints.
293
+ For example it can be used to force foreign key constraint on polymorphic association:
294
+
295
+ create_table :comments do |t|
296
+ t.string :subject_type
297
+ t.integer :subject_id
298
+ t.virtual :subject_photo_id, :as => "CASE subject_type WHEN 'Photo' THEN subject_id END"
299
+ t.virtual :subject_event_id, :as => "CASE subject_type WHEN 'Event' THEN subject_id END"
300
+ end
301
+
302
+ add_foreign_key :comments, :photos, :column => :subject_photo_id
303
+ add_foreign_key :comments, :events, :column => :subject_event_id
304
+
305
+ For backward compatibility reasons it is possible to use `:default` option in the `create_table` instead of `:as` option.
306
+ But this is deprecated and may be removed in the future version.
307
+
251
308
  ### Oracle specific schema statements and data types
252
309
 
253
310
  There are several additional schema statements and data types available that you can use in database migrations:
@@ -257,7 +314,6 @@ There are several additional schema statements and data types available that you
257
314
  * You can create table with primary key trigger using `:primary_key_trigger => true` option for `create_table`
258
315
  * You can define columns with `raw` type which maps to Oracle's `RAW` type
259
316
  * You can add table and column comments with `:comment` option
260
- * On Oracle 11g you can define `virtual` columns with calculation formula in `:default` option
261
317
  * Default tablespaces can be specified for tables, indexes, clobs and blobs, for example:
262
318
 
263
319
  ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces =
@@ -285,7 +341,7 @@ Please verify that
285
341
  require 'rubygems'
286
342
  gem 'activerecord'
287
343
  gem 'activerecord-oracle_enhanced-adapter'
288
- require 'activerecord'
344
+ require 'active_record'
289
345
  ActiveRecord::Base.establish_connection(:adapter => "oracle_enhanced", :database => "database",:username => "user",:password => "password")
290
346
 
291
347
  and see if it is successful (use your correct database, username and password)
@@ -320,37 +376,6 @@ LINKS
320
376
  * Discuss at Oracle enhanced adapter group: http://groups.google.com/group/oracle-enhanced
321
377
  * Blog posts about Oracle enhanced adapter can be found at http://blog.rayapps.com/category/oracle_enhanced
322
378
 
323
- CONTRIBUTORS
324
- ------------
325
-
326
- * Raimonds Simanovskis
327
- * Jorge Dias
328
- * James Wylder
329
- * Rob Christie
330
- * Nate Wieger
331
- * Edgars Beigarts
332
- * Lachlan Laycock
333
- * toddwf
334
- * Anton Jenkins
335
- * Dave Smylie
336
- * Alex Rothenberg
337
- * Billy Reisinger
338
- * David Blain
339
- * Joe Khoobyar
340
- * Edvard Majakari
341
- * Beau Fabry
342
- * Simon Chiang
343
- * Peter Nyberg
344
- * Dwayne Litzenberger
345
- * Aaron Patterson
346
- * Darcy Schultz
347
- * Alexi Rahman
348
- * Joeri Samson
349
- * Luca Bernardo Ciddio
350
- * Sam Baskinger
351
- * Benjamin Ortega
352
- * Yasuo Honda
353
-
354
379
  LICENSE
355
380
  -------
356
381
 
@@ -375,4 +400,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
375
400
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
376
401
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
377
402
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
378
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
403
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -33,9 +33,22 @@ RSpec::Core::RakeTask.new(:rcov) do |t|
33
33
  t.rcov_opts = ['--exclude', '/Library,spec/']
34
34
  end
35
35
 
36
+ desc "Clear test database"
37
+ task :clear do
38
+ require "./spec/spec_helper"
39
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
40
+ require "active_support/core_ext"
41
+ ActiveRecord::Base.connection.execute_structure_dump(ActiveRecord::Base.connection.full_drop)
42
+ ActiveRecord::Base.connection.execute("PURGE RECYCLEBIN") rescue nil
43
+ end
44
+
45
+ # Clear test database before running spec and rcov
46
+ task :spec => :clear
47
+ task :rcov => :clear
48
+
36
49
  task :default => :spec
37
50
 
38
- require 'rake/rdoctask'
51
+ require 'rdoc/task'
39
52
  Rake::RDocTask.new do |rdoc|
40
53
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
54
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.1
1
+ 1.4.2.rc1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{activerecord-oracle_enhanced-adapter}
8
- s.version = "1.4.1"
8
+ s.version = "1.4.2.rc1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{Raimonds Simanovskis}]
12
- s.date = %q{2012-01-27}
12
+ s.date = %q{2012-11-13}
13
13
  s.description = %q{Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases.
14
14
  This adapter is superset of original ActiveRecord Oracle adapter.
15
15
  }
@@ -656,7 +656,11 @@ module ActiveRecord
656
656
  def explain(arel, binds = [])
657
657
  sql = "EXPLAIN PLAN FOR #{to_sql(arel)}"
658
658
  return if sql =~ /FROM all_/
659
- exec_query(sql, 'EXPLAIN', binds)
659
+ if ORACLE_ENHANCED_CONNECTION == :jdbc
660
+ exec_query(sql, 'EXPLAIN', binds)
661
+ else
662
+ exec_query(sql, 'EXPLAIN')
663
+ end
660
664
  select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", 'EXPLAIN').join("\n")
661
665
  end
662
666
 
@@ -855,12 +859,12 @@ module ActiveRecord
855
859
 
856
860
  klass = klass.constantize rescue nil
857
861
  if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base)
858
- write_lobs(table_name, klass, fixture)
862
+ write_lobs(table_name, klass, fixture, klass.lob_columns)
859
863
  end
860
864
  end
861
865
 
862
- # Writes LOB values from attributes, as indicated by the LOB columns of klass.
863
- def write_lobs(table_name, klass, attributes) #:nodoc:
866
+ # Writes LOB values from attributes for specified columns
867
+ def write_lobs(table_name, klass, attributes, columns) #:nodoc:
864
868
  # is class with composite primary key>
865
869
  is_with_cpk = klass.respond_to?(:composite?) && klass.composite?
866
870
  if is_with_cpk
@@ -868,7 +872,7 @@ module ActiveRecord
868
872
  else
869
873
  id = quote(attributes[klass.primary_key])
870
874
  end
871
- klass.columns.select { |col| col.sql_type =~ /LOB$/i }.each do |col|
875
+ columns.each do |col|
872
876
  value = attributes[col.name]
873
877
  # changed sequence of next two lines - should check if value is nil before converting to yaml
874
878
  next if value.nil? || (value == '')
@@ -930,11 +934,14 @@ module ActiveRecord
930
934
  SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
931
935
  i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
932
936
  LOWER(i.tablespace_name) AS tablespace_name,
933
- LOWER(c.column_name) AS column_name, e.column_expression
937
+ LOWER(c.column_name) AS column_name, e.column_expression,
938
+ atc.virtual_column
934
939
  FROM all_indexes#{db_link} i
935
940
  JOIN all_ind_columns#{db_link} c ON c.index_name = i.index_name AND c.index_owner = i.owner
936
941
  LEFT OUTER JOIN all_ind_expressions#{db_link} e ON e.index_name = i.index_name AND
937
942
  e.index_owner = i.owner AND e.column_position = c.column_position
943
+ LEFT OUTER JOIN all_tab_cols#{db_link} atc ON i.table_name = atc.table_name AND
944
+ c.column_name = atc.column_name AND i.owner = atc.owner AND atc.hidden_column = 'NO'
938
945
  WHERE i.owner = '#{owner}'
939
946
  AND i.table_owner = '#{owner}'
940
947
  AND NOT EXISTS (SELECT uc.index_name FROM all_constraints uc
@@ -969,7 +976,16 @@ module ActiveRecord
969
976
  row['tablespace_name'] == default_tablespace_name ? nil : row['tablespace_name'], [])
970
977
  current_index = row['index_name']
971
978
  end
972
- all_schema_indexes.last.columns << (row['column_expression'] || row['column_name'].downcase)
979
+
980
+ # Functional index columns and virtual columns both get stored as column expressions,
981
+ # but re-creating a virtual column index as an expression (instead of using the virtual column's name)
982
+ # results in a ORA-54018 error. Thus, we only want the column expression value returned
983
+ # when the column is not virtual.
984
+ if row['column_expression'] && row['virtual_column'] != 'YES'
985
+ all_schema_indexes.last.columns << row['column_expression']
986
+ else
987
+ all_schema_indexes.last.columns << row['column_name'].downcase
988
+ end
973
989
  end
974
990
  end
975
991
 
@@ -1089,8 +1105,10 @@ module ActiveRecord
1089
1105
  row['sql_type'] += "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
1090
1106
  end
1091
1107
 
1108
+ is_virtual = row['virtual_column']=='YES'
1109
+
1092
1110
  # clean up odd default spacing from Oracle
1093
- if row['data_default']
1111
+ if row['data_default'] && !is_virtual
1094
1112
  row['data_default'].sub!(/^(.*?)\s*$/, '\1')
1095
1113
 
1096
1114
  # If a default contains a newline these cleanup regexes need to
@@ -1106,7 +1124,7 @@ module ActiveRecord
1106
1124
  # pass table name for table specific column definitions
1107
1125
  table_name,
1108
1126
  # pass column type if specified in class definition
1109
- get_type_for_column(table_name, oracle_downcase(row['name'])), row['virtual_column']=='YES')
1127
+ get_type_for_column(table_name, oracle_downcase(row['name'])), is_virtual)
1110
1128
  end
1111
1129
  end
1112
1130
 
@@ -62,23 +62,35 @@ module ActiveRecord
62
62
  # After setting large objects to empty, select the OCI8::LOB
63
63
  # and write back the data.
64
64
  if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR >= 1
65
+ before_update :record_changed_lobs
65
66
  after_update :enhanced_write_lobs
66
67
  else
68
+ before_update :record_changed_lobs
67
69
  after_save :enhanced_write_lobs
68
70
  end
69
71
  def enhanced_write_lobs #:nodoc:
70
72
  if connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
71
73
  !(self.class.custom_create_method || self.class.custom_update_method)
72
- connection.write_lobs(self.class.table_name, self.class, attributes)
74
+ connection.write_lobs(self.class.table_name, self.class, attributes, @changed_lob_columns || self.class.lob_columns)
73
75
  end
74
76
  end
77
+ def record_changed_lobs
78
+ @changed_lob_columns = self.class.lob_columns.select{|col| self.send(:"#{col.name}_changed?") && !self.class.readonly_attributes.to_a.include?(col.name)}
79
+ end
75
80
  private :enhanced_write_lobs
81
+ private :record_changed_lobs
76
82
 
77
83
  # Get table comment from schema definition.
78
84
  def self.table_comment
79
85
  connection.table_comment(self.table_name)
80
86
  end
81
87
 
88
+ def self.lob_columns
89
+ columns.select do |column|
90
+ column.respond_to?(:lob?) && column.lob?
91
+ end
92
+ end
93
+
82
94
  def self.virtual_columns
83
95
  columns.select do |column|
84
96
  column.respond_to?(:virtual?) && column.virtual?
@@ -3,13 +3,14 @@ module ActiveRecord
3
3
  class OracleEnhancedColumn < Column
4
4
 
5
5
  attr_reader :table_name, :forced_column_type, :nchar, :virtual_column_data_default #:nodoc:
6
-
6
+
7
7
  def initialize(name, default, sql_type = nil, null = true, table_name = nil, forced_column_type = nil, virtual=false) #:nodoc:
8
8
  @table_name = table_name
9
9
  @forced_column_type = forced_column_type
10
10
  @virtual = virtual
11
- super(name, default, sql_type, null)
12
11
  @virtual_column_data_default = default.inspect if virtual
12
+ default = nil if virtual
13
+ super(name, default, sql_type, null)
13
14
  # Is column NCHAR or NVARCHAR2 (will need to use N'...' value quoting for these data types)?
14
15
  # Define only when needed as adapter "quote" method will check at first if instance variable is defined.
15
16
  @nchar = true if @type == :string && sql_type[0,1] == 'N'
@@ -25,6 +26,10 @@ module ActiveRecord
25
26
  @virtual
26
27
  end
27
28
 
29
+ def lob?
30
+ self.sql_type =~ /LOB$/i
31
+ end
32
+
28
33
  # convert something to a boolean
29
34
  # added y as boolean value
30
35
  def self.value_to_boolean(value) #:nodoc:
@@ -21,6 +21,7 @@ module ActiveRecord
21
21
  # * <tt>:tablespace</tt>
22
22
  # * <tt>:sync</tt> - 'MANUAL', 'EVERY "interval-string"' or 'ON COMMIT' (defaults to 'MANUAL').
23
23
  # * <tt>:lexer</tt> - Lexer options (e.g. <tt>:type => 'BASIC_LEXER', :base_letter => true</tt>).
24
+ # * <tt>:wordlist</tt> - Wordlist options (e.g. <tt>:type => 'BASIC_WORDLIST', :prefix_index => true</tt>).
24
25
  # * <tt>:transactional</tt> - When +true+, the CONTAINS operator will process inserted and updated rows.
25
26
  #
26
27
  # ===== Examples
@@ -64,6 +65,9 @@ module ActiveRecord
64
65
  # ====== Creating index using lexer
65
66
  # add_context_index :posts, :title, :lexer => { :type => 'BASIC_LEXER', :base_letter => true, ... }
66
67
  #
68
+ # ====== Creating index using wordlist
69
+ # add_context_index :posts, :title, :wordlist => { :type => 'BASIC_WORDLIST', :prefix_index => true, ... }
70
+ #
67
71
  # ====== Creating transactional index (will reindex changed rows when querying)
68
72
  # add_context_index :posts, :title, :transactional => true
69
73
  #
@@ -106,6 +110,12 @@ module ActiveRecord
106
110
  create_lexer_preference(lexer_name, lexer_type, lexer_options)
107
111
  parameters << "LEXER #{lexer_name}"
108
112
  end
113
+ if options[:wordlist] && (wordlist_type = options[:wordlist][:type])
114
+ wordlist_name = default_wordlist_name(index_name)
115
+ (wordlist_options = options[:wordlist].dup).delete(:type)
116
+ create_wordlist_preference(wordlist_name, wordlist_type, wordlist_options)
117
+ parameters << "WORDLIST #{wordlist_name}"
118
+ end
109
119
  if options[:transactional]
110
120
  parameters << "TRANSACTIONAL"
111
121
  end
@@ -246,6 +256,23 @@ module ActiveRecord
246
256
  execute sql
247
257
  end
248
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
269
+ end
270
+ sql << "CTX_DDL.SET_ATTRIBUTE('#{wordlist_name}', '#{key}', #{plsql_value});\n"
271
+ end
272
+ sql << "END;\n"
273
+ execute sql
274
+ end
275
+
249
276
  def drop_ctx_preference(preference_name)
250
277
  execute "BEGIN CTX_DDL.DROP_PREFERENCE('#{preference_name}'); END;" rescue nil
251
278
  end
@@ -288,6 +315,10 @@ module ActiveRecord
288
315
  "#{index_name}_lex"
289
316
  end
290
317
 
318
+ def default_wordlist_name(index_name)
319
+ "#{index_name}_wl"
320
+ end
321
+
291
322
  module BaseClassMethods
292
323
  # Declare that model table has context index defined.
293
324
  # As a result <tt>contains</tt> class scope method is defined.
@@ -5,7 +5,7 @@ module ActiveRecord #:nodoc:
5
5
  module InstanceMethods #:nodoc:
6
6
  private
7
7
 
8
- def field_changed?(attr, old, value)
8
+ def _field_changed?(attr, old, value)
9
9
  if column = column_for_attribute(attr)
10
10
  # Added also :decimal type
11
11
  if (column.type == :integer || column.type == :decimal) && column.null && (old.nil? || old == 0) && value.blank?
@@ -35,5 +35,10 @@ end
35
35
  if ActiveRecord::Base.method_defined?(:changed?)
36
36
  ActiveRecord::Base.class_eval do
37
37
  include ActiveRecord::ConnectionAdapters::OracleEnhancedDirty::InstanceMethods
38
+ # Starting with rails 3.2.9 the method #field_changed?
39
+ # was renamed to #_field_changed?
40
+ if private_method_defined?(:field_changed?)
41
+ alias_method :field_changed?, :_field_changed?
42
+ end
38
43
  end
39
44
  end