activerecord-oracle_enhanced-adapter 1.1.9 → 1.2.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/History.txt +11 -0
- data/README.txt +6 -2
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +771 -907
- data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +71 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +64 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +352 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +346 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +2 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb +126 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +2 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +200 -97
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +170 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +40 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +11 -6
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +148 -53
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +13 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +27 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +10 -6
- data/spec/spec_helper.rb +51 -6
- metadata +11 -2
@@ -0,0 +1,346 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'oci8' unless self.class.const_defined? :OCI8
|
5
|
+
|
6
|
+
# RSI: added mapping for TIMESTAMP / WITH TIME ZONE / LOCAL TIME ZONE types
|
7
|
+
# currently Ruby-OCI8 does not support fractional seconds for timestamps
|
8
|
+
OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP] = OCI8::BindType::OraDate
|
9
|
+
OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_TZ] = OCI8::BindType::OraDate
|
10
|
+
OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_LTZ] = OCI8::BindType::OraDate
|
11
|
+
rescue LoadError
|
12
|
+
# OCI8 driver is unavailable.
|
13
|
+
error_message = "ERROR: ActiveRecord oracle_enhanced adapter could not load ruby-oci8 library. "+
|
14
|
+
"Please install ruby-oci8 library or gem."
|
15
|
+
if defined?(RAILS_DEFAULT_LOGGER)
|
16
|
+
RAILS_DEFAULT_LOGGER.error error_message
|
17
|
+
else
|
18
|
+
STDERR.puts error_message
|
19
|
+
end
|
20
|
+
raise LoadError
|
21
|
+
end
|
22
|
+
|
23
|
+
module ActiveRecord
|
24
|
+
module ConnectionAdapters
|
25
|
+
|
26
|
+
# OCI database interface for MRI
|
27
|
+
class OracleEnhancedOCIConnection < OracleEnhancedConnection
|
28
|
+
|
29
|
+
def initialize(config)
|
30
|
+
@raw_connection = OCI8EnhancedAutoRecover.new(config, OracleEnhancedOCIFactory)
|
31
|
+
end
|
32
|
+
|
33
|
+
def auto_retry
|
34
|
+
@raw_connection.auto_retry if @raw_connection
|
35
|
+
end
|
36
|
+
|
37
|
+
def auto_retry=(value)
|
38
|
+
@raw_connection.auto_retry = value if @raw_connection
|
39
|
+
end
|
40
|
+
|
41
|
+
def logoff
|
42
|
+
@raw_connection.logoff
|
43
|
+
@raw_connection.active = false
|
44
|
+
end
|
45
|
+
|
46
|
+
def commit
|
47
|
+
@raw_connection.commit
|
48
|
+
end
|
49
|
+
|
50
|
+
def rollback
|
51
|
+
@raw_connection.rollback
|
52
|
+
end
|
53
|
+
|
54
|
+
def autocommit?
|
55
|
+
@raw_connection.autocommit?
|
56
|
+
end
|
57
|
+
|
58
|
+
def autocommit=(value)
|
59
|
+
@raw_connection.autocommit = value
|
60
|
+
end
|
61
|
+
|
62
|
+
# Checks connection, returns true if active. Note that ping actively
|
63
|
+
# checks the connection, while #active? simply returns the last
|
64
|
+
# known state.
|
65
|
+
def ping
|
66
|
+
@raw_connection.ping
|
67
|
+
rescue OCIException => e
|
68
|
+
raise OracleEnhancedConnectionException, e.message
|
69
|
+
end
|
70
|
+
|
71
|
+
def active?
|
72
|
+
@raw_connection.active?
|
73
|
+
end
|
74
|
+
|
75
|
+
def reset!
|
76
|
+
@raw_connection.reset!
|
77
|
+
rescue OCIException => e
|
78
|
+
raise OracleEnhancedConnectionException, e.message
|
79
|
+
end
|
80
|
+
|
81
|
+
def exec(sql, *bindvars, &block)
|
82
|
+
@raw_connection.exec(sql, *bindvars, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
def select(sql, name = nil, return_column_names = false)
|
86
|
+
cursor = @raw_connection.exec(sql)
|
87
|
+
cols = cursor.get_col_names.map { |x| oracle_downcase(x) }
|
88
|
+
rows = []
|
89
|
+
|
90
|
+
while row = cursor.fetch
|
91
|
+
hash = Hash.new
|
92
|
+
|
93
|
+
cols.each_with_index do |col, i|
|
94
|
+
hash[col] =
|
95
|
+
case row[i]
|
96
|
+
when OCI8::LOB
|
97
|
+
if name == 'Writable Large Object'
|
98
|
+
row[i]
|
99
|
+
else
|
100
|
+
data = row[i].read
|
101
|
+
# In Ruby 1.9.1 always change encoding to ASCII-8BIT for binaries
|
102
|
+
data.force_encoding('ASCII-8BIT') if data.respond_to?(:force_encoding) && row[i].is_a?(OCI8::BLOB)
|
103
|
+
data
|
104
|
+
end
|
105
|
+
# ruby-oci8 1.0 returns OraDate
|
106
|
+
when OraDate
|
107
|
+
d = row[i]
|
108
|
+
# RSI: added emulate_dates_by_column_name functionality
|
109
|
+
# if emulate_dates_by_column_name && self.class.is_date_column?(col)
|
110
|
+
# d.to_date
|
111
|
+
# elsif
|
112
|
+
if OracleEnhancedAdapter.emulate_dates && (d.hour == 0 && d.minute == 0 && d.second == 0)
|
113
|
+
d.to_date
|
114
|
+
else
|
115
|
+
# code from Time.time_with_datetime_fallback
|
116
|
+
begin
|
117
|
+
Time.send(Base.default_timezone, d.year, d.month, d.day, d.hour, d.minute, d.second)
|
118
|
+
rescue
|
119
|
+
offset = Base.default_timezone.to_sym == :local ? ::DateTime.local_offset : 0
|
120
|
+
::DateTime.civil(d.year, d.month, d.day, d.hour, d.minute, d.second, offset)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
# ruby-oci8 2.0 returns Time or DateTime
|
124
|
+
when Time, DateTime
|
125
|
+
d = row[i]
|
126
|
+
if OracleEnhancedAdapter.emulate_dates && (d.hour == 0 && d.min == 0 && d.sec == 0)
|
127
|
+
d.to_date
|
128
|
+
else
|
129
|
+
# recreate Time or DateTime using Base.default_timezone
|
130
|
+
begin
|
131
|
+
Time.send(Base.default_timezone, d.year, d.month, d.day, d.hour, d.min, d.sec)
|
132
|
+
rescue
|
133
|
+
offset = Base.default_timezone.to_sym == :local ? ::DateTime.local_offset : 0
|
134
|
+
::DateTime.civil(d.year, d.month, d.day, d.hour, d.min, d.sec, offset)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
# RSI: added emulate_integers_by_column_name functionality
|
138
|
+
when Float
|
139
|
+
n = row[i]
|
140
|
+
if OracleEnhancedAdapter.emulate_integers_by_column_name && OracleEnhancedAdapter.is_integer_column?(col)
|
141
|
+
n.to_i
|
142
|
+
else
|
143
|
+
n
|
144
|
+
end
|
145
|
+
# ruby-oci8 2.0 returns OraNumber - convert it to Integer or BigDecimal
|
146
|
+
when OraNumber
|
147
|
+
n = row[i]
|
148
|
+
n == (n_to_i = n.to_i) ? n_to_i : BigDecimal.new(n.to_s)
|
149
|
+
else row[i]
|
150
|
+
end unless col == 'raw_rnum_'
|
151
|
+
end
|
152
|
+
|
153
|
+
rows << hash
|
154
|
+
end
|
155
|
+
|
156
|
+
return_column_names ? [rows, cols] : rows
|
157
|
+
ensure
|
158
|
+
cursor.close if cursor
|
159
|
+
end
|
160
|
+
|
161
|
+
def write_lob(lob, value, is_binary = false)
|
162
|
+
lob.write value
|
163
|
+
end
|
164
|
+
|
165
|
+
def describe(name)
|
166
|
+
quoted_name = OracleEnhancedAdapter.valid_table_name?(name) ? name : "\"#{name}\""
|
167
|
+
@raw_connection.describe(quoted_name)
|
168
|
+
rescue OCIException => e
|
169
|
+
raise OracleEnhancedConnectionException, e.message
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
# The OracleEnhancedOCIFactory factors out the code necessary to connect and
|
175
|
+
# configure an Oracle/OCI connection.
|
176
|
+
class OracleEnhancedOCIFactory #:nodoc:
|
177
|
+
def self.new_connection(config)
|
178
|
+
username, password, database = config[:username].to_s, config[:password].to_s, config[:database].to_s
|
179
|
+
privilege = config[:privilege] && config[:privilege].to_sym
|
180
|
+
async = config[:allow_concurrency]
|
181
|
+
prefetch_rows = config[:prefetch_rows] || 100
|
182
|
+
cursor_sharing = config[:cursor_sharing] || 'similar'
|
183
|
+
|
184
|
+
conn = OCI8.new username, password, database, privilege
|
185
|
+
conn.exec %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'}
|
186
|
+
conn.exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'} rescue nil
|
187
|
+
conn.autocommit = true
|
188
|
+
conn.non_blocking = true if async
|
189
|
+
conn.prefetch_rows = prefetch_rows
|
190
|
+
conn.exec "alter session set cursor_sharing = #{cursor_sharing}" rescue nil
|
191
|
+
conn
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
class OCI8 #:nodoc:
|
202
|
+
|
203
|
+
class Cursor #:nodoc:
|
204
|
+
if method_defined? :define_a_column
|
205
|
+
# This OCI8 patch is required with the ruby-oci8 1.0.x or lower.
|
206
|
+
# Set OCI8::BindType::Mapping[] to change the column type
|
207
|
+
# when using ruby-oci8 2.0.
|
208
|
+
|
209
|
+
alias :enhanced_define_a_column_pre_ar :define_a_column
|
210
|
+
def define_a_column(i)
|
211
|
+
case do_ocicall(@ctx) { @parms[i - 1].attrGet(OCI_ATTR_DATA_TYPE) }
|
212
|
+
when 8; @stmt.defineByPos(i, String, 65535) # Read LONG values
|
213
|
+
when 187; @stmt.defineByPos(i, OraDate) # Read TIMESTAMP values
|
214
|
+
when 108
|
215
|
+
if @parms[i - 1].attrGet(OCI_ATTR_TYPE_NAME) == 'XMLTYPE'
|
216
|
+
@stmt.defineByPos(i, String, 65535)
|
217
|
+
else
|
218
|
+
raise 'unsupported datatype'
|
219
|
+
end
|
220
|
+
else enhanced_define_a_column_pre_ar i
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
if OCI8.public_method_defined?(:describe_table)
|
227
|
+
# ruby-oci8 2.0 or upper
|
228
|
+
|
229
|
+
def describe(name)
|
230
|
+
info = describe_table(name.to_s)
|
231
|
+
raise %Q{"DESC #{name}" failed} if info.nil?
|
232
|
+
[info.obj_schema, info.obj_name]
|
233
|
+
end
|
234
|
+
else
|
235
|
+
# ruby-oci8 1.0.x or lower
|
236
|
+
|
237
|
+
# missing constant from oci8 < 0.1.14
|
238
|
+
OCI_PTYPE_UNK = 0 unless defined?(OCI_PTYPE_UNK)
|
239
|
+
|
240
|
+
# Uses the describeAny OCI call to find the target owner and table_name
|
241
|
+
# indicated by +name+, parsing through synonynms as necessary. Returns
|
242
|
+
# an array of [owner, table_name].
|
243
|
+
def describe(name)
|
244
|
+
@desc ||= @@env.alloc(OCIDescribe)
|
245
|
+
@desc.attrSet(OCI_ATTR_DESC_PUBLIC, -1) if VERSION >= '0.1.14'
|
246
|
+
do_ocicall(@ctx) { @desc.describeAny(@svc, name.to_s, OCI_PTYPE_UNK) } rescue raise %Q{"DESC #{name}" failed; does it exist?}
|
247
|
+
info = @desc.attrGet(OCI_ATTR_PARAM)
|
248
|
+
|
249
|
+
case info.attrGet(OCI_ATTR_PTYPE)
|
250
|
+
when OCI_PTYPE_TABLE, OCI_PTYPE_VIEW
|
251
|
+
owner = info.attrGet(OCI_ATTR_OBJ_SCHEMA)
|
252
|
+
table_name = info.attrGet(OCI_ATTR_OBJ_NAME)
|
253
|
+
[owner, table_name]
|
254
|
+
when OCI_PTYPE_SYN
|
255
|
+
schema = info.attrGet(OCI_ATTR_SCHEMA_NAME)
|
256
|
+
name = info.attrGet(OCI_ATTR_NAME)
|
257
|
+
describe(schema + '.' + name)
|
258
|
+
else raise %Q{"DESC #{name}" failed; not a table or view.}
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
# The OCI8AutoRecover class enhances the OCI8 driver with auto-recover and
|
266
|
+
# reset functionality. If a call to #exec fails, and autocommit is turned on
|
267
|
+
# (ie., we're not in the middle of a longer transaction), it will
|
268
|
+
# automatically reconnect and try again. If autocommit is turned off,
|
269
|
+
# this would be dangerous (as the earlier part of the implied transaction
|
270
|
+
# may have failed silently if the connection died) -- so instead the
|
271
|
+
# connection is marked as dead, to be reconnected on it's next use.
|
272
|
+
class OCI8EnhancedAutoRecover < DelegateClass(OCI8) #:nodoc:
|
273
|
+
attr_accessor :active
|
274
|
+
alias :active? :active
|
275
|
+
|
276
|
+
cattr_accessor :auto_retry
|
277
|
+
class << self
|
278
|
+
alias :auto_retry? :auto_retry
|
279
|
+
end
|
280
|
+
@@auto_retry = false
|
281
|
+
|
282
|
+
def initialize(config, factory)
|
283
|
+
@active = true
|
284
|
+
@config = config
|
285
|
+
@factory = factory
|
286
|
+
@connection = @factory.new_connection @config
|
287
|
+
super @connection
|
288
|
+
end
|
289
|
+
|
290
|
+
# Checks connection, returns true if active. Note that ping actively
|
291
|
+
# checks the connection, while #active? simply returns the last
|
292
|
+
# known state.
|
293
|
+
def ping
|
294
|
+
@connection.exec("select 1 from dual") { |r| nil }
|
295
|
+
@active = true
|
296
|
+
rescue
|
297
|
+
@active = false
|
298
|
+
raise
|
299
|
+
end
|
300
|
+
|
301
|
+
# Resets connection, by logging off and creating a new connection.
|
302
|
+
def reset!
|
303
|
+
logoff rescue nil
|
304
|
+
begin
|
305
|
+
@connection = @factory.new_connection @config
|
306
|
+
__setobj__ @connection
|
307
|
+
@active = true
|
308
|
+
rescue
|
309
|
+
@active = false
|
310
|
+
raise
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
# ORA-00028: your session has been killed
|
315
|
+
# ORA-01012: not logged on
|
316
|
+
# ORA-03113: end-of-file on communication channel
|
317
|
+
# ORA-03114: not connected to ORACLE
|
318
|
+
# ORA-03135: connection lost contact
|
319
|
+
LOST_CONNECTION_ERROR_CODES = [ 28, 1012, 3113, 3114, 3135 ]
|
320
|
+
|
321
|
+
# Adds auto-recovery functionality.
|
322
|
+
#
|
323
|
+
# See: http://www.jiubao.org/ruby-oci8/api.en.html#label-11
|
324
|
+
def exec(sql, *bindvars, &block)
|
325
|
+
should_retry = self.class.auto_retry? && autocommit?
|
326
|
+
|
327
|
+
begin
|
328
|
+
@connection.exec(sql, *bindvars, &block)
|
329
|
+
rescue OCIException => e
|
330
|
+
raise unless LOST_CONNECTION_ERROR_CODES.include?(e.code)
|
331
|
+
@active = false
|
332
|
+
raise unless should_retry
|
333
|
+
should_retry = false
|
334
|
+
reset! rescue nil
|
335
|
+
retry
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
# RSI: otherwise not working in Ruby 1.9.1
|
340
|
+
if RUBY_VERSION =~ /^1\.9/
|
341
|
+
def describe(name)
|
342
|
+
@connection.describe(name)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
end
|
@@ -40,7 +40,8 @@ module ActiveRecord #:nodoc:
|
|
40
40
|
base.instance_eval do
|
41
41
|
alias_method_chain :create, :custom_method
|
42
42
|
# insert after dirty checking in Rails 2.1
|
43
|
-
|
43
|
+
# in Ruby 1.9 methods names are returned as symbols
|
44
|
+
if private_instance_methods.include?('update_without_dirty') || private_instance_methods.include?(:update_without_dirty)
|
44
45
|
alias_method :update_without_custom_method, :update_without_dirty
|
45
46
|
alias_method :update_without_dirty, :update_with_custom_method
|
46
47
|
else
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module ActiveRecord #:nodoc:
|
2
|
+
module ConnectionAdapters #:nodoc:
|
3
|
+
module OracleEnhancedReservedWords #:nodoc:
|
4
|
+
|
5
|
+
RESERVED_WORDS = {
|
6
|
+
"ACCESS" => true,
|
7
|
+
"ADD" => true,
|
8
|
+
"ALL" => true,
|
9
|
+
"ALTER" => true,
|
10
|
+
"AND" => true,
|
11
|
+
"ANY" => true,
|
12
|
+
"AS" => true,
|
13
|
+
"ASC" => true,
|
14
|
+
"AUDIT" => true,
|
15
|
+
"BETWEEN" => true,
|
16
|
+
"BY" => true,
|
17
|
+
"CHAR" => true,
|
18
|
+
"CHECK" => true,
|
19
|
+
"CLUSTER" => true,
|
20
|
+
"COLUMN" => true,
|
21
|
+
"COMMENT" => true,
|
22
|
+
"COMPRESS" => true,
|
23
|
+
"CONNECT" => true,
|
24
|
+
"CREATE" => true,
|
25
|
+
"CURRENT" => true,
|
26
|
+
"DATE" => true,
|
27
|
+
"DECIMAL" => true,
|
28
|
+
"DEFAULT" => true,
|
29
|
+
"DELETE" => true,
|
30
|
+
"DESC" => true,
|
31
|
+
"DISTINCT" => true,
|
32
|
+
"DROP" => true,
|
33
|
+
"ELSE" => true,
|
34
|
+
"EXCLUSIVE" => true,
|
35
|
+
"EXISTS" => true,
|
36
|
+
"FILE" => true,
|
37
|
+
"FLOAT" => true,
|
38
|
+
"FOR" => true,
|
39
|
+
"FROM" => true,
|
40
|
+
"GRANT" => true,
|
41
|
+
"GROUP" => true,
|
42
|
+
"HAVING" => true,
|
43
|
+
"IDENTIFIED" => true,
|
44
|
+
"IMMEDIATE" => true,
|
45
|
+
"IN" => true,
|
46
|
+
"INCREMENT" => true,
|
47
|
+
"INDEX" => true,
|
48
|
+
"INITIAL" => true,
|
49
|
+
"INSERT" => true,
|
50
|
+
"INTEGER" => true,
|
51
|
+
"INTERSECT" => true,
|
52
|
+
"INTO" => true,
|
53
|
+
"IS" => true,
|
54
|
+
"LEVEL" => true,
|
55
|
+
"LIKE" => true,
|
56
|
+
"LOCK" => true,
|
57
|
+
"LONG" => true,
|
58
|
+
"MAXEXTENTS" => true,
|
59
|
+
"MINUS" => true,
|
60
|
+
"MLSLABEL" => true,
|
61
|
+
"MODE" => true,
|
62
|
+
"MODIFY" => true,
|
63
|
+
"NOAUDIT" => true,
|
64
|
+
"NOCOMPRESS" => true,
|
65
|
+
"NOT" => true,
|
66
|
+
"NOWAIT" => true,
|
67
|
+
"NULL" => true,
|
68
|
+
"NUMBER" => true,
|
69
|
+
"OF" => true,
|
70
|
+
"OFFLINE" => true,
|
71
|
+
"ON" => true,
|
72
|
+
"ONLINE" => true,
|
73
|
+
"OPTION" => true,
|
74
|
+
"OR" => true,
|
75
|
+
"ORDER" => true,
|
76
|
+
"PCTFREE" => true,
|
77
|
+
"PRIOR" => true,
|
78
|
+
"PRIVILEGES" => true,
|
79
|
+
"PUBLIC" => true,
|
80
|
+
"RAW" => true,
|
81
|
+
"RENAME" => true,
|
82
|
+
"RESOURCE" => true,
|
83
|
+
"REVOKE" => true,
|
84
|
+
"ROW" => true,
|
85
|
+
"ROWID" => true,
|
86
|
+
"ROWNUM" => true,
|
87
|
+
"ROWS" => true,
|
88
|
+
"SELECT" => true,
|
89
|
+
"SESSION" => true,
|
90
|
+
"SET" => true,
|
91
|
+
"SHARE" => true,
|
92
|
+
"SIZE" => true,
|
93
|
+
"SMALLINT" => true,
|
94
|
+
"START" => true,
|
95
|
+
"SUCCESSFUL" => true,
|
96
|
+
"SYNONYM" => true,
|
97
|
+
"SYSDATE" => true,
|
98
|
+
"TABLE" => true,
|
99
|
+
"THEN" => true,
|
100
|
+
"TO" => true,
|
101
|
+
"TRIGGER" => true,
|
102
|
+
"UID" => true,
|
103
|
+
"UNION" => true,
|
104
|
+
"UNIQUE" => true,
|
105
|
+
"UPDATE" => true,
|
106
|
+
"USER" => true,
|
107
|
+
"VALIDATE" => true,
|
108
|
+
"VALUES" => true,
|
109
|
+
"VARCHAR" => true,
|
110
|
+
"VARCHAR2" => true,
|
111
|
+
"VIEW" => true,
|
112
|
+
"WHENEVER" => true,
|
113
|
+
"WHERE" => true,
|
114
|
+
"WITH" => true
|
115
|
+
}
|
116
|
+
|
117
|
+
def quote_oracle_reserved_words(name)
|
118
|
+
RESERVED_WORDS[name.to_s.upcase].nil? ? name : "\"#{name}\""
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
|
125
|
+
include ActiveRecord::ConnectionAdapters::OracleEnhancedReservedWords
|
126
|
+
end
|