activerecord-oracle_enhanced-adapter 1.3.2 → 1.4.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.
- data/Gemfile +0 -2
- data/History.txt +19 -0
- data/README.md +378 -0
- data/RUNNING_TESTS.md +45 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/activerecord-oracle_enhanced-adapter.gemspec +6 -9
- data/lib/active_record/connection_adapters/oracle_enhanced.rake +34 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +209 -57
- data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +22 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +17 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +19 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +75 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +41 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +40 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +10 -3
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +49 -10
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +54 -54
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +33 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +66 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +162 -13
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +1 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +1 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +43 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +150 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +5 -4
- data/spec/spec_helper.rb +3 -1
- metadata +38 -52
- data/README.rdoc +0 -89
- data/RUNNING_TESTS.rdoc +0 -28
@@ -61,7 +61,11 @@ module ActiveRecord
|
|
61
61
|
|
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
|
+
after_update :enhanced_write_lobs
|
66
|
+
else
|
67
|
+
after_save :enhanced_write_lobs
|
68
|
+
end
|
65
69
|
def enhanced_write_lobs #:nodoc:
|
66
70
|
if connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
|
67
71
|
!(self.class.custom_create_method || self.class.custom_update_method)
|
@@ -74,6 +78,23 @@ module ActiveRecord
|
|
74
78
|
def self.table_comment
|
75
79
|
connection.table_comment(self.table_name)
|
76
80
|
end
|
81
|
+
|
82
|
+
if ActiveRecord::VERSION::MAJOR < 3
|
83
|
+
def attributes_with_quotes_with_virtual_columns(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
|
84
|
+
virtual_columns = self.class.columns.select(& :virtual?).map(&:name)
|
85
|
+
attributes_with_quotes_without_virtual_columns(include_primary_key, include_readonly_attributes, attribute_names - virtual_columns)
|
86
|
+
end
|
87
|
+
|
88
|
+
alias_method_chain :attributes_with_quotes, :virtual_columns
|
89
|
+
else
|
90
|
+
def arel_attributes_values_with_virtual_columns(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
|
91
|
+
virtual_columns = self.class.columns.select(& :virtual?).map(&:name)
|
92
|
+
arel_attributes_values_without_virtual_columns(include_primary_key, include_readonly_attributes, attribute_names - virtual_columns)
|
93
|
+
end
|
94
|
+
|
95
|
+
alias_method_chain :arel_attributes_values, :virtual_columns
|
96
|
+
end
|
97
|
+
|
77
98
|
end
|
78
99
|
|
79
100
|
end
|
@@ -2,22 +2,29 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters #:nodoc:
|
3
3
|
class OracleEnhancedColumn < Column
|
4
4
|
|
5
|
-
attr_reader :table_name, :forced_column_type, :nchar #:nodoc:
|
5
|
+
attr_reader :table_name, :forced_column_type, :nchar, :virtual_column_data_default #:nodoc:
|
6
6
|
|
7
|
-
def initialize(name, default, sql_type = nil, null = true, table_name = nil, forced_column_type = nil) #:nodoc:
|
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
|
+
@virtual = virtual
|
10
11
|
super(name, default, sql_type, null)
|
12
|
+
@virtual_column_data_default = default.inspect if virtual
|
11
13
|
# Is column NCHAR or NVARCHAR2 (will need to use N'...' value quoting for these data types)?
|
12
14
|
# Define only when needed as adapter "quote" method will check at first if instance variable is defined.
|
13
15
|
@nchar = true if @type == :string && sql_type[0,1] == 'N'
|
14
16
|
end
|
15
17
|
|
16
18
|
def type_cast(value) #:nodoc:
|
19
|
+
return OracleEnhancedColumn::string_to_raw(value) if type == :raw
|
17
20
|
return guess_date_or_time(value) if type == :datetime && OracleEnhancedAdapter.emulate_dates
|
18
21
|
super
|
19
22
|
end
|
20
23
|
|
24
|
+
def virtual?
|
25
|
+
@virtual
|
26
|
+
end
|
27
|
+
|
21
28
|
# convert something to a boolean
|
22
29
|
# added y as boolean value
|
23
30
|
def self.value_to_boolean(value) #:nodoc:
|
@@ -42,6 +49,11 @@ module ActiveRecord
|
|
42
49
|
super
|
43
50
|
end
|
44
51
|
|
52
|
+
# convert RAW column values back to byte strings.
|
53
|
+
def self.string_to_raw(string) #:nodoc:
|
54
|
+
string
|
55
|
+
end
|
56
|
+
|
45
57
|
# Get column comment from schema definition.
|
46
58
|
# Will work only if using default ActiveRecord connection.
|
47
59
|
def comment
|
@@ -63,6 +75,8 @@ module ActiveRecord
|
|
63
75
|
else
|
64
76
|
:decimal
|
65
77
|
end
|
78
|
+
when /raw/i
|
79
|
+
:raw
|
66
80
|
when /char/i
|
67
81
|
if OracleEnhancedAdapter.emulate_booleans_from_strings &&
|
68
82
|
OracleEnhancedAdapter.is_boolean_column?(name, field_type, table_name)
|
@@ -119,4 +133,4 @@ module ActiveRecord
|
|
119
133
|
|
120
134
|
end
|
121
135
|
|
122
|
-
end
|
136
|
+
end
|
@@ -13,6 +13,16 @@ module ActiveRecord
|
|
13
13
|
# Use +contains+ ActiveRecord model instance method to add CONTAINS where condition
|
14
14
|
# and order by score of matched results.
|
15
15
|
#
|
16
|
+
# Options:
|
17
|
+
#
|
18
|
+
# * <tt>:name</tt>
|
19
|
+
# * <tt>:index_column</tt>
|
20
|
+
# * <tt>:index_column_trigger_on</tt>
|
21
|
+
# * <tt>:tablespace</tt>
|
22
|
+
# * <tt>:sync</tt> - 'MANUAL', 'EVERY "interval-string"' or 'ON COMMIT' (defaults to 'MANUAL').
|
23
|
+
# * <tt>:lexer</tt> - Lexer options (e.g. <tt>:type => 'BASIC_LEXER', :base_letter => true</tt>).
|
24
|
+
# * <tt>:transactional</tt> - When +true+, the CONTAINS operator will process inserted and updated rows.
|
25
|
+
#
|
16
26
|
# ===== Examples
|
17
27
|
#
|
18
28
|
# ====== Creating single column index
|
@@ -54,6 +64,9 @@ module ActiveRecord
|
|
54
64
|
# ====== Creating index using lexer
|
55
65
|
# add_context_index :posts, :title, :lexer => { :type => 'BASIC_LEXER', :base_letter => true, ... }
|
56
66
|
#
|
67
|
+
# ====== Creating transactional index (will reindex changed rows when querying)
|
68
|
+
# add_context_index :posts, :title, :transactional => true
|
69
|
+
#
|
57
70
|
def add_context_index(table_name, column_name, options = {})
|
58
71
|
self.all_schema_indexes = nil
|
59
72
|
column_names = Array(column_name)
|
@@ -63,7 +76,7 @@ module ActiveRecord
|
|
63
76
|
|
64
77
|
quoted_column_name = quote_column_name(options[:index_column] || column_names.first)
|
65
78
|
if options[:index_column_trigger_on]
|
66
|
-
raise ArgumentError, "Option :index_column should be specified together with :
|
79
|
+
raise ArgumentError, "Option :index_column should be specified together with :index_column_trigger_on option" \
|
67
80
|
unless options[:index_column]
|
68
81
|
create_index_column_trigger(table_name, index_name, options[:index_column], options[:index_column_trigger_on])
|
69
82
|
end
|
@@ -93,6 +106,9 @@ module ActiveRecord
|
|
93
106
|
create_lexer_preference(lexer_name, lexer_type, lexer_options)
|
94
107
|
parameters << "LEXER #{lexer_name}"
|
95
108
|
end
|
109
|
+
if options[:transactional]
|
110
|
+
parameters << "TRANSACTIONAL"
|
111
|
+
end
|
96
112
|
unless parameters.empty?
|
97
113
|
sql << " PARAMETERS ('#{parameters.join(' ')}')"
|
98
114
|
end
|
@@ -119,8 +135,8 @@ module ActiveRecord
|
|
119
135
|
|
120
136
|
def create_datastore_procedure(table_name, procedure_name, column_names, options)
|
121
137
|
quoted_table_name = quote_table_name(table_name)
|
122
|
-
select_queries = column_names.
|
123
|
-
|
138
|
+
select_queries, column_names = column_names.partition { |c| c.to_s =~ /^\s*SELECT\s+/i }
|
139
|
+
select_queries = select_queries.map { |s| s.strip.gsub(/\s+/, ' ') }
|
124
140
|
keys, selected_columns = parse_select_queries(select_queries)
|
125
141
|
quoted_column_names = (column_names+keys).map{|col| quote_column_name(col)}
|
126
142
|
execute compress_lines(<<-SQL)
|
@@ -2,19 +2,28 @@ begin
|
|
2
2
|
require "java"
|
3
3
|
require "jruby"
|
4
4
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
5
|
+
# ojdbc6.jar or ojdbc5.jar file should be in JRUBY_HOME/lib or should be in ENV['PATH'] or load path
|
6
|
+
|
7
|
+
java_version = java.lang.System.getProperty("java.version")
|
8
|
+
ojdbc_jar = if java_version =~ /^1.5/
|
9
|
+
"ojdbc5.jar"
|
10
|
+
elsif java_version >= '1.6'
|
11
|
+
"ojdbc6.jar"
|
12
|
+
else
|
13
|
+
nil
|
14
|
+
end
|
8
15
|
|
9
|
-
unless ENV_JAVA['java.class.path'] =~ Regexp.new(ojdbc_jar)
|
16
|
+
unless ojdbc_jar.nil? || ENV_JAVA['java.class.path'] =~ Regexp.new(ojdbc_jar)
|
10
17
|
# On Unix environment variable should be PATH, on Windows it is sometimes Path
|
11
|
-
env_path = ENV["PATH"] || ENV["Path"] || ''
|
12
|
-
|
18
|
+
env_path = (ENV["PATH"] || ENV["Path"] || '').split(/[:;]/)
|
19
|
+
# Look for JDBC driver at first in lib subdirectory (application specific JDBC file version)
|
20
|
+
# then in Ruby load path and finally in environment PATH
|
21
|
+
if ojdbc_jar_path = ['./lib'].concat($LOAD_PATH).concat(env_path).find{|d| File.exists?(File.join(d,ojdbc_jar))}
|
13
22
|
require File.join(ojdbc_jar_path,ojdbc_jar)
|
14
23
|
end
|
15
24
|
end
|
16
25
|
|
17
|
-
java.sql.DriverManager.registerDriver Java::oracle.jdbc.
|
26
|
+
java.sql.DriverManager.registerDriver Java::oracle.jdbc.OracleDriver.new
|
18
27
|
|
19
28
|
# set tns_admin property from TNS_ADMIN environment variable
|
20
29
|
if !java.lang.System.get_property("oracle.net.tns_admin") && ENV["TNS_ADMIN"]
|
@@ -23,7 +32,7 @@ begin
|
|
23
32
|
|
24
33
|
rescue LoadError, NameError
|
25
34
|
# JDBC driver is unavailable.
|
26
|
-
raise LoadError, "ERROR: ActiveRecord oracle_enhanced adapter could not load Oracle JDBC driver. Please install
|
35
|
+
raise LoadError, "ERROR: ActiveRecord oracle_enhanced adapter could not load Oracle JDBC driver. Please install #{ojdbc_jar || "Oracle JDBC"} library."
|
27
36
|
end
|
28
37
|
|
29
38
|
|
@@ -199,7 +208,7 @@ module ActiveRecord
|
|
199
208
|
begin
|
200
209
|
yield if block_given?
|
201
210
|
rescue NativeException => e
|
202
|
-
raise unless e.message =~ /^java\.sql\.SQL(Recoverable)?Exception: (Closed Connection|Io exception:|No more data to read from socket)/
|
211
|
+
raise unless e.message =~ /^java\.sql\.SQL(Recoverable)?Exception: (Closed Connection|Io exception:|No more data to read from socket|IO Error:)/
|
203
212
|
@active = false
|
204
213
|
raise unless should_retry
|
205
214
|
should_retry = false
|
@@ -288,17 +297,26 @@ module ActiveRecord
|
|
288
297
|
@raw_statement = raw_statement
|
289
298
|
end
|
290
299
|
|
291
|
-
def bind_param(position, value)
|
292
|
-
java_value = ruby_to_java_value(value)
|
300
|
+
def bind_param(position, value, col_type = nil)
|
301
|
+
java_value = ruby_to_java_value(value, col_type)
|
293
302
|
case value
|
294
303
|
when Integer
|
295
|
-
@raw_statement.
|
304
|
+
@raw_statement.setLong(position, java_value)
|
296
305
|
when Float
|
297
306
|
@raw_statement.setFloat(position, java_value)
|
298
307
|
when BigDecimal
|
299
308
|
@raw_statement.setBigDecimal(position, java_value)
|
300
309
|
when String
|
301
|
-
|
310
|
+
case col_type
|
311
|
+
when :text
|
312
|
+
@raw_statement.setClob(position, java_value)
|
313
|
+
when :binary
|
314
|
+
@raw_statement.setBlob(position, java_value)
|
315
|
+
when :raw
|
316
|
+
@raw_statement.setString(position, OracleEnhancedAdapter.encode_raw(java_value))
|
317
|
+
else
|
318
|
+
@raw_statement.setString(position, java_value)
|
319
|
+
end
|
302
320
|
when Date, DateTime
|
303
321
|
@raw_statement.setDATE(position, java_value)
|
304
322
|
when Time
|
@@ -313,12 +331,24 @@ module ActiveRecord
|
|
313
331
|
end
|
314
332
|
end
|
315
333
|
|
334
|
+
def bind_returning_param(position, bind_type)
|
335
|
+
@returning_positions ||= []
|
336
|
+
@returning_positions << position
|
337
|
+
if bind_type == Integer
|
338
|
+
@raw_statement.registerReturnParameter(position, java.sql.Types::BIGINT)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
316
342
|
def exec
|
317
343
|
@raw_result_set = @raw_statement.executeQuery
|
318
344
|
get_metadata
|
319
345
|
true
|
320
346
|
end
|
321
347
|
|
348
|
+
def exec_update
|
349
|
+
@raw_statement.executeUpdate
|
350
|
+
end
|
351
|
+
|
322
352
|
def get_metadata
|
323
353
|
metadata = @raw_result_set.getMetaData
|
324
354
|
column_count = metadata.getColumnCount
|
@@ -345,16 +375,41 @@ module ActiveRecord
|
|
345
375
|
end
|
346
376
|
end
|
347
377
|
|
378
|
+
def get_returning_param(position, type)
|
379
|
+
rs_position = @returning_positions.index(position) + 1
|
380
|
+
rs = @raw_statement.getReturnResultSet
|
381
|
+
if rs.next
|
382
|
+
# Assuming that primary key will not be larger as long max value
|
383
|
+
returning_id = rs.getLong(rs_position)
|
384
|
+
rs.wasNull ? nil : returning_id
|
385
|
+
else
|
386
|
+
nil
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
348
390
|
def close
|
349
391
|
@raw_statement.close
|
350
392
|
end
|
351
393
|
|
352
394
|
private
|
353
395
|
|
354
|
-
def ruby_to_java_value(value)
|
396
|
+
def ruby_to_java_value(value, col_type = nil)
|
355
397
|
case value
|
356
|
-
when Fixnum,
|
398
|
+
when Fixnum, Float
|
357
399
|
value
|
400
|
+
when String
|
401
|
+
case col_type
|
402
|
+
when :text
|
403
|
+
clob = Java::OracleSql::CLOB.createTemporary(@connection.raw_connection, false, Java::OracleSql::CLOB::DURATION_SESSION)
|
404
|
+
clob.setString(1, value)
|
405
|
+
clob
|
406
|
+
when :binary
|
407
|
+
blob = Java::OracleSql::BLOB.createTemporary(@connection.raw_connection, false, Java::OracleSql::BLOB::DURATION_SESSION)
|
408
|
+
blob.setBytes(1, value.to_java_bytes)
|
409
|
+
blob
|
410
|
+
else
|
411
|
+
value
|
412
|
+
end
|
358
413
|
when BigDecimal
|
359
414
|
java.math.BigDecimal.new(value.to_s)
|
360
415
|
when Date, DateTime
|
@@ -438,7 +493,7 @@ module ActiveRecord
|
|
438
493
|
else
|
439
494
|
BigDecimal.new(d.stringValue)
|
440
495
|
end
|
441
|
-
when :VARCHAR2, :CHAR, :LONG
|
496
|
+
when :VARCHAR2, :CHAR, :LONG, :NVARCHAR2, :NCHAR
|
442
497
|
rset.getString(i)
|
443
498
|
when :DATE
|
444
499
|
if dt = rset.getDATE(i)
|
@@ -452,7 +507,7 @@ module ActiveRecord
|
|
452
507
|
else
|
453
508
|
nil
|
454
509
|
end
|
455
|
-
when :TIMESTAMP, :TIMESTAMPTZ, :TIMESTAMPLTZ
|
510
|
+
when :TIMESTAMP, :TIMESTAMPTZ, :TIMESTAMPLTZ, :"TIMESTAMP WITH TIME ZONE", :"TIMESTAMP WITH LOCAL TIME ZONE"
|
456
511
|
ts = rset.getTimestamp(i)
|
457
512
|
ts && Time.send(Base.default_timezone, ts.year + 1900, ts.month + 1, ts.date, ts.hours, ts.minutes, ts.seconds,
|
458
513
|
ts.nanos / 1000)
|
@@ -460,6 +515,9 @@ module ActiveRecord
|
|
460
515
|
get_lob_value ? lob_to_ruby_value(rset.getClob(i)) : rset.getClob(i)
|
461
516
|
when :BLOB
|
462
517
|
get_lob_value ? lob_to_ruby_value(rset.getBlob(i)) : rset.getBlob(i)
|
518
|
+
when :RAW
|
519
|
+
raw_value = rset.getRAW(i)
|
520
|
+
raw_value && raw_value.getBytes.to_a.pack('C*')
|
463
521
|
else
|
464
522
|
nil
|
465
523
|
end
|
@@ -26,6 +26,16 @@ module ActiveRecord
|
|
26
26
|
@owner = config[:username].to_s.upcase
|
27
27
|
end
|
28
28
|
|
29
|
+
def raw_oci_connection
|
30
|
+
if @raw_connection.is_a? OCI8
|
31
|
+
@raw_connection
|
32
|
+
# ActiveRecord Oracle enhanced adapter puts OCI8EnhancedAutoRecover wrapper around OCI8
|
33
|
+
# in this case we need to pass original OCI8 connection
|
34
|
+
else
|
35
|
+
@raw_connection.instance_variable_get(:@connection)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
29
39
|
def auto_retry
|
30
40
|
@raw_connection.auto_retry if @raw_connection
|
31
41
|
end
|
@@ -103,14 +113,38 @@ module ActiveRecord
|
|
103
113
|
@raw_cursor = raw_cursor
|
104
114
|
end
|
105
115
|
|
106
|
-
def bind_param(position, value)
|
107
|
-
|
116
|
+
def bind_param(position, value, col_type = nil)
|
117
|
+
if value.nil?
|
118
|
+
@raw_cursor.bind_param(position, nil, String)
|
119
|
+
else
|
120
|
+
case col_type
|
121
|
+
when :text, :binary
|
122
|
+
# ruby-oci8 cannot create CLOB/BLOB from ''
|
123
|
+
lob_value = value == '' ? ' ' : value
|
124
|
+
bind_type = col_type == :text ? OCI8::CLOB : OCI8::BLOB
|
125
|
+
ora_value = bind_type.new(@connection.raw_oci_connection, lob_value)
|
126
|
+
ora_value.size = 0 if value == ''
|
127
|
+
@raw_cursor.bind_param(position, ora_value)
|
128
|
+
when :raw
|
129
|
+
@raw_cursor.bind_param(position, OracleEnhancedAdapter.encode_raw(value))
|
130
|
+
else
|
131
|
+
@raw_cursor.bind_param(position, value)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def bind_returning_param(position, bind_type)
|
137
|
+
@raw_cursor.bind_param(position, nil, bind_type)
|
108
138
|
end
|
109
139
|
|
110
140
|
def exec
|
111
141
|
@raw_cursor.exec
|
112
142
|
end
|
113
143
|
|
144
|
+
def exec_update
|
145
|
+
@raw_cursor.exec
|
146
|
+
end
|
147
|
+
|
114
148
|
def get_col_names
|
115
149
|
@raw_cursor.get_col_names
|
116
150
|
end
|
@@ -124,9 +158,14 @@ module ActiveRecord
|
|
124
158
|
end
|
125
159
|
end
|
126
160
|
|
161
|
+
def get_returning_param(position, type)
|
162
|
+
@raw_cursor[position]
|
163
|
+
end
|
164
|
+
|
127
165
|
def close
|
128
166
|
@raw_cursor.close
|
129
167
|
end
|
168
|
+
|
130
169
|
end
|
131
170
|
|
132
171
|
def select(sql, name = nil, return_column_names = false)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# define accessors before requiring ruby-plsql as these accessors are used in clob writing callback and should be
|
2
2
|
# available also if ruby-plsql could not be loaded
|
3
3
|
ActiveRecord::Base.class_eval do
|
4
|
-
if respond_to? :
|
5
|
-
class_inheritable_accessor :custom_create_method, :custom_update_method, :custom_delete_method
|
6
|
-
elsif respond_to? :class_attribute
|
4
|
+
if respond_to? :class_attribute
|
7
5
|
class_attribute :custom_create_method, :custom_update_method, :custom_delete_method
|
6
|
+
elsif respond_to? :class_inheritable_accessor
|
7
|
+
class_inheritable_accessor :custom_create_method, :custom_update_method, :custom_delete_method
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -10,11 +10,36 @@ module ActiveRecord
|
|
10
10
|
:tablespace, :columns) #:nodoc:
|
11
11
|
end
|
12
12
|
|
13
|
+
module OracleEnhancedColumnDefinition
|
14
|
+
def self.included(base) #:nodoc:
|
15
|
+
base.class_eval do
|
16
|
+
alias_method_chain :to_sql, :virtual_columns
|
17
|
+
alias to_s :to_sql
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_sql_with_virtual_columns
|
22
|
+
if type==:virtual
|
23
|
+
"#{base.quote_column_name(name)} AS (#{default})"
|
24
|
+
else
|
25
|
+
to_sql_without_virtual_columns
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def lob?
|
30
|
+
['CLOB', 'BLOB'].include?(sql_type)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
13
34
|
module OracleEnhancedSchemaDefinitions #:nodoc:
|
14
35
|
def self.included(base)
|
15
36
|
base::TableDefinition.class_eval do
|
16
37
|
include OracleEnhancedTableDefinition
|
17
38
|
end
|
39
|
+
|
40
|
+
base::ColumnDefinition.class_eval do
|
41
|
+
include OracleEnhancedColumnDefinition
|
42
|
+
end
|
18
43
|
|
19
44
|
# Available starting from ActiveRecord 2.1
|
20
45
|
base::Table.class_eval do
|
@@ -31,10 +56,21 @@ module ActiveRecord
|
|
31
56
|
alias to_s :to_sql
|
32
57
|
end
|
33
58
|
|
59
|
+
def raw(name, options={})
|
60
|
+
column(name, :raw, options)
|
61
|
+
end
|
62
|
+
|
34
63
|
def self.included(base) #:nodoc:
|
35
64
|
base.class_eval do
|
36
65
|
alias_method_chain :references, :foreign_keys
|
37
66
|
alias_method_chain :to_sql, :foreign_keys
|
67
|
+
|
68
|
+
def virtual(* args)
|
69
|
+
options = args.extract_options!
|
70
|
+
column_names = args
|
71
|
+
column_names.each { |name| column(name, :virtual, options) }
|
72
|
+
end
|
73
|
+
|
38
74
|
end
|
39
75
|
end
|
40
76
|
|
@@ -88,6 +124,10 @@ module ActiveRecord
|
|
88
124
|
sql << ', ' << (foreign_keys * ', ') unless foreign_keys.blank?
|
89
125
|
sql
|
90
126
|
end
|
127
|
+
|
128
|
+
def lob_columns
|
129
|
+
columns.select(&:lob?)
|
130
|
+
end
|
91
131
|
|
92
132
|
private
|
93
133
|
def foreign_keys
|