activerecord-oracle_enhanced-adapter 1.4.1 → 1.4.2.rc1
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.
- data/Gemfile +1 -0
- data/History.md +16 -1
- data/README.md +60 -35
- data/Rakefile +14 -1
- data/VERSION +1 -1
- data/activerecord-oracle_enhanced-adapter.gemspec +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +27 -9
- data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +13 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +7 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +31 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +6 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +17 -5
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +2 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +29 -11
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +9 -4
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +31 -7
- data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +5 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +34 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +22 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +1 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +52 -6
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +20 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +6 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +79 -21
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +203 -35
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +17 -1
- data/spec/spec_helper.rb +3 -1
- metadata +74 -51
data/Gemfile
CHANGED
data/History.md
CHANGED
@@ -1,4 +1,19 @@
|
|
1
|
-
### 1.4.
|
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
|
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 '
|
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 '
|
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.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.
|
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-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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'])),
|
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
|
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
|