activerecord-oracle_enhanced-adapter 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +11 -0
- data/{README.txt → README.rdoc} +11 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +65 -34
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +57 -68
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +40 -35
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +15 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +42 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +82 -16
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +25 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +64 -0
- data/spec/spec_helper.rb +17 -10
- metadata +44 -12
data/History.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 1.2.1 2009-06-07
|
2
|
+
|
3
|
+
* Enhancements
|
4
|
+
* caching of table indexes query which makes schema dump much faster
|
5
|
+
* Bug fixes:
|
6
|
+
* return Date (and not DateTime) values for :date column value before year 1970
|
7
|
+
* fixed after_create/update/destroy callbacks with plsql custom methods
|
8
|
+
* fixed creation of large integers in JRuby
|
9
|
+
* Made test tasks respect RAILS_ENV
|
10
|
+
* fixed support for composite primary keys for tables with LOBs
|
11
|
+
|
1
12
|
== 1.2.0 2009-03-22
|
2
13
|
|
3
14
|
* Enhancements
|
data/{README.txt → README.rdoc}
RENAMED
@@ -29,6 +29,17 @@ Bugs and enhancement requests can be reported at http://rsim.lighthouseapp.com/p
|
|
29
29
|
|
30
30
|
* sudo gem install activerecord-oracle_enhanced-adapter
|
31
31
|
|
32
|
+
== CONTRIBUTORS:
|
33
|
+
|
34
|
+
* Raimonds Simanovskis
|
35
|
+
* Jorge Dias
|
36
|
+
* James Wylder
|
37
|
+
* Rob Christie
|
38
|
+
* Nate Wieger
|
39
|
+
* Edgars Beigarts
|
40
|
+
* Lachlan Laycock
|
41
|
+
* toddwf
|
42
|
+
|
32
43
|
== LICENSE:
|
33
44
|
|
34
45
|
(The MIT License)
|
@@ -137,9 +137,9 @@ module ActiveRecord
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
# RSI: convert Time value to Date for :date columns
|
140
|
+
# RSI: convert Time or DateTime value to Date for :date columns
|
141
141
|
def self.string_to_date(string)
|
142
|
-
return string.to_date if string.is_a?(Time)
|
142
|
+
return string.to_date if string.is_a?(Time) || string.is_a?(DateTime)
|
143
143
|
super
|
144
144
|
end
|
145
145
|
|
@@ -346,8 +346,11 @@ module ActiveRecord
|
|
346
346
|
# unescaped table name should start with letter and
|
347
347
|
# contain letters, digits, _, $ or #
|
348
348
|
# can be prefixed with schema name
|
349
|
+
# CamelCase table names should be quoted
|
349
350
|
def self.valid_table_name?(name)
|
350
|
-
name.to_s
|
351
|
+
name = name.to_s
|
352
|
+
name =~ /^([A-Za-z_0-9]+\.)?[a-z][a-z_0-9\$#]*$/ ||
|
353
|
+
name =~ /^([A-Za-z_0-9]+\.)?[A-Z][A-Z_0-9\$#]*$/ ? true : false
|
351
354
|
end
|
352
355
|
|
353
356
|
# abstract_adapter calls quote_column_name from quote_table_name, so prevent that
|
@@ -515,15 +518,26 @@ module ActiveRecord
|
|
515
518
|
|
516
519
|
# Writes LOB values from attributes, as indicated by the LOB columns of klass.
|
517
520
|
def write_lobs(table_name, klass, attributes)
|
518
|
-
|
521
|
+
# is class with composite primary key>
|
522
|
+
is_with_cpk = klass.respond_to?(:composite?) && klass.composite?
|
523
|
+
if is_with_cpk
|
524
|
+
id = klass.primary_key.map {|pk| attributes[pk.to_s] }
|
525
|
+
else
|
526
|
+
id = quote(attributes[klass.primary_key])
|
527
|
+
end
|
519
528
|
klass.columns.select { |col| col.sql_type =~ /LOB$/i }.each do |col|
|
520
529
|
value = attributes[col.name]
|
521
530
|
# RSI: changed sequence of next two lines - should check if value is nil before converting to yaml
|
522
531
|
next if value.nil? || (value == '')
|
523
532
|
value = value.to_yaml if col.text? && klass.serialized_attributes[col.name]
|
524
533
|
uncached do
|
525
|
-
|
534
|
+
if is_with_cpk
|
535
|
+
lob = select_one("SELECT #{col.name} FROM #{table_name} WHERE #{klass.composite_where_clause(id)} FOR UPDATE",
|
536
|
+
'Writable Large Object')[col.name]
|
537
|
+
else
|
538
|
+
lob = select_one("SELECT #{col.name} FROM #{table_name} WHERE #{klass.primary_key} = #{id} FOR UPDATE",
|
526
539
|
'Writable Large Object')[col.name]
|
540
|
+
end
|
527
541
|
@connection.write_lob(lob, value, col.type == :binary)
|
528
542
|
end
|
529
543
|
end
|
@@ -556,36 +570,45 @@ module ActiveRecord
|
|
556
570
|
|
557
571
|
# RSI: changed select from user_tables to all_tables - much faster in large data dictionaries
|
558
572
|
def tables(name = nil) #:nodoc:
|
559
|
-
select_all("select lower(table_name) name from all_tables where owner = sys_context('userenv','session_user')").map {|t| t['name']}
|
573
|
+
select_all("select decode(table_name,upper(table_name),lower(table_name),table_name) name from all_tables where owner = sys_context('userenv','session_user')").map {|t| t['name']}
|
560
574
|
end
|
561
575
|
|
562
|
-
|
563
|
-
(owner, table_name) = @connection.describe(table_name)
|
564
|
-
result = select_all(<<-SQL, name)
|
565
|
-
SELECT lower(i.index_name) as index_name, i.uniqueness, lower(c.column_name) as column_name
|
566
|
-
FROM all_indexes i, all_ind_columns c
|
567
|
-
WHERE i.table_name = '#{table_name}'
|
568
|
-
AND i.owner = '#{owner}'
|
569
|
-
AND i.table_owner = '#{owner}'
|
570
|
-
AND c.index_name = i.index_name
|
571
|
-
AND c.index_owner = i.owner
|
572
|
-
AND NOT EXISTS (SELECT uc.index_name FROM all_constraints uc WHERE uc.index_name = i.index_name AND uc.owner = i.owner AND uc.constraint_type = 'P')
|
573
|
-
ORDER BY i.index_name, c.column_position
|
574
|
-
SQL
|
575
|
-
|
576
|
-
current_index = nil
|
577
|
-
indexes = []
|
576
|
+
cattr_accessor :all_schema_indexes
|
578
577
|
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
578
|
+
# This method selects all indexes at once, and caches them in a class variable.
|
579
|
+
# Subsequent index calls get them from the variable, without going to the DB.
|
580
|
+
def indexes(table_name, name = nil)
|
581
|
+
(owner, table_name) = @connection.describe(table_name)
|
582
|
+
unless all_schema_indexes
|
583
|
+
result = select_all(<<-SQL)
|
584
|
+
SELECT lower(i.table_name) as table_name, lower(i.index_name) as index_name, i.uniqueness, lower(c.column_name) as column_name
|
585
|
+
FROM all_indexes i, all_ind_columns c
|
586
|
+
WHERE i.owner = '#{owner}'
|
587
|
+
AND i.table_owner = '#{owner}'
|
588
|
+
AND c.index_name = i.index_name
|
589
|
+
AND c.index_owner = i.owner
|
590
|
+
AND NOT EXISTS (SELECT uc.index_name FROM all_constraints uc WHERE uc.index_name = i.index_name AND uc.owner = i.owner AND uc.constraint_type = 'P')
|
591
|
+
ORDER BY i.index_name, c.column_position
|
592
|
+
SQL
|
593
|
+
|
594
|
+
current_index = nil
|
595
|
+
self.all_schema_indexes = []
|
596
|
+
|
597
|
+
result.each do |row|
|
598
|
+
# have to keep track of indexes because above query returns dups
|
599
|
+
# there is probably a better query we could figure out
|
600
|
+
if current_index != row['index_name']
|
601
|
+
self.all_schema_indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(row['table_name'], row['index_name'], row['uniqueness'] == "UNIQUE", [])
|
602
|
+
current_index = row['index_name']
|
603
|
+
end
|
604
|
+
|
605
|
+
self.all_schema_indexes.last.columns << row['column_name']
|
583
606
|
end
|
584
|
-
|
585
|
-
indexes.last.columns << row['column_name']
|
586
607
|
end
|
587
|
-
|
588
|
-
indexes
|
608
|
+
|
609
|
+
# Return the indexes just for the requested table, since AR is structured that way
|
610
|
+
table_name = table_name.downcase
|
611
|
+
all_schema_indexes.select{|i| i.table == table_name}
|
589
612
|
end
|
590
613
|
|
591
614
|
# RSI: set ignored columns for table
|
@@ -723,7 +746,15 @@ module ActiveRecord
|
|
723
746
|
execute "DROP SEQUENCE #{seq_name}" rescue nil
|
724
747
|
end
|
725
748
|
|
749
|
+
# clear cached indexes when adding new index
|
750
|
+
def add_index(table_name, column_name, options = {})
|
751
|
+
self.all_schema_indexes = nil
|
752
|
+
super
|
753
|
+
end
|
754
|
+
|
755
|
+
# clear cached indexes when removing index
|
726
756
|
def remove_index(table_name, options = {}) #:nodoc:
|
757
|
+
self.all_schema_indexes = nil
|
727
758
|
execute "DROP INDEX #{index_name(table_name, options)}"
|
728
759
|
end
|
729
760
|
|
@@ -822,12 +853,12 @@ module ActiveRecord
|
|
822
853
|
end
|
823
854
|
|
824
855
|
def structure_dump #:nodoc:
|
825
|
-
s = select_all("select sequence_name from user_sequences").inject("") do |structure, seq|
|
856
|
+
s = select_all("select sequence_name from user_sequences order by 1").inject("") do |structure, seq|
|
826
857
|
structure << "create sequence #{seq.to_a.first.last};\n\n"
|
827
858
|
end
|
828
859
|
|
829
860
|
# RSI: changed select from user_tables to all_tables - much faster in large data dictionaries
|
830
|
-
select_all("select table_name from all_tables where owner = sys_context('userenv','session_user')").inject(s) do |structure, table|
|
861
|
+
select_all("select table_name from all_tables where owner = sys_context('userenv','session_user') order by 1").inject(s) do |structure, table|
|
831
862
|
ddl = "create table #{table.to_a.first.last} (\n "
|
832
863
|
cols = select_all(%Q{
|
833
864
|
select column_name, data_type, data_length, char_used, char_length, data_precision, data_scale, data_default, nullable
|
@@ -855,12 +886,12 @@ module ActiveRecord
|
|
855
886
|
end
|
856
887
|
|
857
888
|
def structure_drop #:nodoc:
|
858
|
-
s = select_all("select sequence_name from user_sequences").inject("") do |drop, seq|
|
889
|
+
s = select_all("select sequence_name from user_sequences order by 1").inject("") do |drop, seq|
|
859
890
|
drop << "drop sequence #{seq.to_a.first.last};\n\n"
|
860
891
|
end
|
861
892
|
|
862
893
|
# RSI: changed select from user_tables to all_tables - much faster in large data dictionaries
|
863
|
-
select_all("select table_name from all_tables where owner = sys_context('userenv','session_user')").inject(s) do |drop, table|
|
894
|
+
select_all("select table_name from all_tables where owner = sys_context('userenv','session_user') order by 1").inject(s) do |drop, table|
|
864
895
|
drop << "drop table #{table.to_a.first.last} cascade constraints;\n\n"
|
865
896
|
end
|
866
897
|
end
|
@@ -72,6 +72,9 @@ module ActiveRecord
|
|
72
72
|
# Set session time zone to current time zone
|
73
73
|
@raw_connection.setSessionTimeZone(java.util.TimeZone.default.getID)
|
74
74
|
|
75
|
+
# Set default number of rows to prefetch
|
76
|
+
# @raw_connection.setDefaultRowPrefetch(prefetch_rows) if prefetch_rows
|
77
|
+
|
75
78
|
# default schema owner
|
76
79
|
@owner = username.upcase
|
77
80
|
|
@@ -156,7 +159,7 @@ module ActiveRecord
|
|
156
159
|
end
|
157
160
|
|
158
161
|
def exec_no_retry(sql)
|
159
|
-
cs =
|
162
|
+
cs = @raw_connection.prepareCall(sql)
|
160
163
|
case sql
|
161
164
|
when /\A\s*UPDATE/i, /\A\s*INSERT/i, /\A\s*DELETE/i
|
162
165
|
cs.executeUpdate
|
@@ -175,59 +178,35 @@ module ActiveRecord
|
|
175
178
|
end
|
176
179
|
|
177
180
|
def select_no_retry(sql, name = nil, return_column_names = false)
|
178
|
-
stmt =
|
181
|
+
stmt = @raw_connection.prepareStatement(sql)
|
179
182
|
rset = stmt.executeQuery
|
183
|
+
|
184
|
+
# Reuse the same hash for all rows
|
185
|
+
column_hash = {}
|
186
|
+
|
180
187
|
metadata = rset.getMetaData
|
181
188
|
column_count = metadata.getColumnCount
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
189
|
+
|
190
|
+
cols_types_index = (1..column_count).map do |i|
|
191
|
+
col_name = oracle_downcase(metadata.getColumnName(i))
|
192
|
+
next if col_name == 'raw_rnum_'
|
193
|
+
column_hash[col_name] = nil
|
194
|
+
[col_name, metadata.getColumnTypeName(i).to_sym, i]
|
187
195
|
end
|
196
|
+
cols_types_index.delete(nil)
|
188
197
|
|
189
198
|
rows = []
|
190
|
-
|
199
|
+
get_lob_value = !(name == 'Writable Large Object')
|
200
|
+
|
191
201
|
while rset.next
|
192
|
-
hash =
|
193
|
-
|
194
|
-
|
195
|
-
i = i0 + 1
|
196
|
-
hash[col] =
|
197
|
-
case column_type = col_types[i0]
|
198
|
-
when /CLOB/
|
199
|
-
name == 'Writable Large Object' ? rset.getClob(i) : get_ruby_value_from_result_set(rset, i, column_type)
|
200
|
-
when /BLOB/
|
201
|
-
name == 'Writable Large Object' ? rset.getBlob(i) : get_ruby_value_from_result_set(rset, i, column_type)
|
202
|
-
when 'DATE'
|
203
|
-
t = get_ruby_value_from_result_set(rset, i, column_type)
|
204
|
-
# RSI: added emulate_dates_by_column_name functionality
|
205
|
-
# if emulate_dates_by_column_name && self.class.is_date_column?(col)
|
206
|
-
# d.to_date
|
207
|
-
# elsif
|
208
|
-
if t && OracleEnhancedAdapter.emulate_dates && (t.hour == 0 && t.min == 0 && t.sec == 0)
|
209
|
-
t.to_date
|
210
|
-
else
|
211
|
-
# JRuby Time supports time before year 1900 therefore now need to fall back to DateTime
|
212
|
-
t
|
213
|
-
end
|
214
|
-
# RSI: added emulate_integers_by_column_name functionality
|
215
|
-
when "NUMBER"
|
216
|
-
n = get_ruby_value_from_result_set(rset, i, column_type)
|
217
|
-
if n && n.is_a?(Float) && OracleEnhancedAdapter.emulate_integers_by_column_name && OracleEnhancedAdapter.is_integer_column?(col)
|
218
|
-
n.to_i
|
219
|
-
else
|
220
|
-
n
|
221
|
-
end
|
222
|
-
else
|
223
|
-
get_ruby_value_from_result_set(rset, i, column_type)
|
224
|
-
end unless col == 'raw_rnum_'
|
202
|
+
hash = column_hash.dup
|
203
|
+
cols_types_index.each do |col, column_type, i|
|
204
|
+
hash[col] = get_ruby_value_from_result_set(rset, i, column_type, get_lob_value)
|
225
205
|
end
|
226
|
-
|
227
206
|
rows << hash
|
228
207
|
end
|
229
208
|
|
230
|
-
return_column_names ? [rows,
|
209
|
+
return_column_names ? [rows, cols_types_index.map(&:first)] : rows
|
231
210
|
ensure
|
232
211
|
rset.close rescue nil
|
233
212
|
stmt.close rescue nil
|
@@ -284,50 +263,62 @@ module ActiveRecord
|
|
284
263
|
|
285
264
|
private
|
286
265
|
|
287
|
-
def prepare_statement(sql)
|
288
|
-
|
289
|
-
end
|
266
|
+
# def prepare_statement(sql)
|
267
|
+
# @raw_connection.prepareStatement(sql)
|
268
|
+
# end
|
290
269
|
|
291
|
-
def prepare_call(sql, *bindvars)
|
292
|
-
|
293
|
-
end
|
270
|
+
# def prepare_call(sql, *bindvars)
|
271
|
+
# @raw_connection.prepareCall(sql)
|
272
|
+
# end
|
294
273
|
|
295
|
-
def get_ruby_value_from_result_set(rset, i, type_name)
|
274
|
+
def get_ruby_value_from_result_set(rset, i, type_name, get_lob_value = true)
|
296
275
|
case type_name
|
297
|
-
when
|
298
|
-
rset.
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
276
|
+
when :NUMBER
|
277
|
+
# d = rset.getBigDecimal(i)
|
278
|
+
# if d.nil?
|
279
|
+
# nil
|
280
|
+
# elsif d.scale == 0
|
281
|
+
# d.toBigInteger+0
|
282
|
+
# else
|
283
|
+
# # Is there better way how to convert Java BigDecimal to Ruby BigDecimal?
|
284
|
+
# d.toString.to_d
|
285
|
+
# end
|
286
|
+
d = rset.getNUMBER(i)
|
305
287
|
if d.nil?
|
306
288
|
nil
|
307
|
-
elsif d.
|
308
|
-
d.
|
289
|
+
elsif d.isInt
|
290
|
+
Integer(d.stringValue)
|
309
291
|
else
|
310
|
-
|
311
|
-
d.toString.to_d
|
292
|
+
BigDecimal.new(d.stringValue)
|
312
293
|
end
|
313
|
-
when
|
294
|
+
when :VARCHAR2, :CHAR, :LONG
|
295
|
+
rset.getString(i)
|
296
|
+
when :DATE
|
314
297
|
if dt = rset.getDATE(i)
|
315
298
|
d = dt.dateValue
|
316
299
|
t = dt.timeValue
|
317
|
-
|
300
|
+
if OracleEnhancedAdapter.emulate_dates && t.hours == 0 && t.minutes == 0 && t.seconds == 0
|
301
|
+
Date.new(d.year + 1900, d.month + 1, d.date)
|
302
|
+
else
|
303
|
+
Time.send(Base.default_timezone, d.year + 1900, d.month + 1, d.date, t.hours, t.minutes, t.seconds)
|
304
|
+
end
|
318
305
|
else
|
319
306
|
nil
|
320
307
|
end
|
321
|
-
when
|
308
|
+
when :TIMESTAMP, :TIMESTAMPTZ, :TIMESTAMPLTZ
|
322
309
|
ts = rset.getTimestamp(i)
|
323
310
|
ts && Time.send(Base.default_timezone, ts.year + 1900, ts.month + 1, ts.date, ts.hours, ts.minutes, ts.seconds,
|
324
311
|
ts.nanos / 1000)
|
312
|
+
when :CLOB
|
313
|
+
get_lob_value ? lob_to_ruby_value(rset.getClob(i)) : rset.getClob(i)
|
314
|
+
when :BLOB
|
315
|
+
get_lob_value ? lob_to_ruby_value(rset.getBlob(i)) : rset.getBlob(i)
|
325
316
|
else
|
326
317
|
nil
|
327
318
|
end
|
328
319
|
end
|
329
320
|
|
330
|
-
def
|
321
|
+
def lob_to_ruby_value(val)
|
331
322
|
case val
|
332
323
|
when ::Java::OracleSql::CLOB
|
333
324
|
if val.isEmptyLob
|
@@ -341,8 +332,6 @@ module ActiveRecord
|
|
341
332
|
else
|
342
333
|
String.from_java_bytes(val.getBytes(1, val.length))
|
343
334
|
end
|
344
|
-
else
|
345
|
-
val
|
346
335
|
end
|
347
336
|
end
|
348
337
|
|
@@ -84,70 +84,75 @@ module ActiveRecord
|
|
84
84
|
|
85
85
|
def select(sql, name = nil, return_column_names = false)
|
86
86
|
cursor = @raw_connection.exec(sql)
|
87
|
-
cols =
|
87
|
+
cols = []
|
88
|
+
# Ignore raw_rnum_ which is used to simulate LIMIT and OFFSET
|
89
|
+
cursor.get_col_names.each do |col_name|
|
90
|
+
col_name = oracle_downcase(col_name)
|
91
|
+
cols << col_name unless col_name == 'raw_rnum_'
|
92
|
+
end
|
93
|
+
# Reuse the same hash for all rows
|
94
|
+
column_hash = {}
|
95
|
+
cols.each {|c| column_hash[c] = nil}
|
88
96
|
rows = []
|
97
|
+
get_lob_value = !(name == 'Writable Large Object')
|
89
98
|
|
90
99
|
while row = cursor.fetch
|
91
|
-
hash =
|
100
|
+
hash = column_hash.dup
|
92
101
|
|
93
102
|
cols.each_with_index do |col, i|
|
94
103
|
hash[col] =
|
95
|
-
case row[i]
|
104
|
+
case v = row[i]
|
105
|
+
# RSI: added emulate_integers_by_column_name functionality
|
106
|
+
when Float
|
107
|
+
# if OracleEnhancedAdapter.emulate_integers_by_column_name && OracleEnhancedAdapter.is_integer_column?(col)
|
108
|
+
# v.to_i
|
109
|
+
# else
|
110
|
+
# v
|
111
|
+
# end
|
112
|
+
v == (v_to_i = v.to_i) ? v_to_i : v
|
113
|
+
# ruby-oci8 2.0 returns OraNumber - convert it to Integer or BigDecimal
|
114
|
+
when OraNumber
|
115
|
+
v == (v_to_i = v.to_i) ? v_to_i : BigDecimal.new(v.to_s)
|
116
|
+
when String
|
117
|
+
v
|
96
118
|
when OCI8::LOB
|
97
|
-
if
|
98
|
-
|
99
|
-
else
|
100
|
-
data = row[i].read
|
119
|
+
if get_lob_value
|
120
|
+
data = v.read
|
101
121
|
# 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) &&
|
122
|
+
data.force_encoding('ASCII-8BIT') if data.respond_to?(:force_encoding) && v.is_a?(OCI8::BLOB)
|
103
123
|
data
|
124
|
+
else
|
125
|
+
v
|
104
126
|
end
|
105
127
|
# ruby-oci8 1.0 returns OraDate
|
106
128
|
when OraDate
|
107
|
-
d = row[i]
|
108
129
|
# RSI: added emulate_dates_by_column_name functionality
|
109
|
-
|
110
|
-
|
111
|
-
# elsif
|
112
|
-
if OracleEnhancedAdapter.emulate_dates && (d.hour == 0 && d.minute == 0 && d.second == 0)
|
113
|
-
d.to_date
|
130
|
+
if OracleEnhancedAdapter.emulate_dates && (v.hour == 0 && v.minute == 0 && v.second == 0)
|
131
|
+
v.to_date
|
114
132
|
else
|
115
133
|
# code from Time.time_with_datetime_fallback
|
116
134
|
begin
|
117
|
-
Time.send(Base.default_timezone,
|
135
|
+
Time.send(Base.default_timezone, v.year, v.month, v.day, v.hour, v.minute, v.second)
|
118
136
|
rescue
|
119
137
|
offset = Base.default_timezone.to_sym == :local ? ::DateTime.local_offset : 0
|
120
|
-
::DateTime.civil(
|
138
|
+
::DateTime.civil(v.year, v.month, v.day, v.hour, v.minute, v.second, offset)
|
121
139
|
end
|
122
140
|
end
|
123
141
|
# ruby-oci8 2.0 returns Time or DateTime
|
124
142
|
when Time, DateTime
|
125
|
-
|
126
|
-
|
127
|
-
d.to_date
|
143
|
+
if OracleEnhancedAdapter.emulate_dates && (v.hour == 0 && v.min == 0 && v.sec == 0)
|
144
|
+
v.to_date
|
128
145
|
else
|
129
146
|
# recreate Time or DateTime using Base.default_timezone
|
130
147
|
begin
|
131
|
-
Time.send(Base.default_timezone,
|
148
|
+
Time.send(Base.default_timezone, v.year, v.month, v.day, v.hour, v.min, v.sec)
|
132
149
|
rescue
|
133
150
|
offset = Base.default_timezone.to_sym == :local ? ::DateTime.local_offset : 0
|
134
|
-
::DateTime.civil(
|
151
|
+
::DateTime.civil(v.year, v.month, v.day, v.hour, v.min, v.sec, offset)
|
135
152
|
end
|
136
153
|
end
|
137
|
-
|
138
|
-
|
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_'
|
154
|
+
else v
|
155
|
+
end
|
151
156
|
end
|
152
157
|
|
153
158
|
rows << hash
|
@@ -38,17 +38,30 @@ module ActiveRecord #:nodoc:
|
|
38
38
|
module InstanceMethods
|
39
39
|
def self.included(base)
|
40
40
|
base.instance_eval do
|
41
|
-
|
41
|
+
if private_instance_methods.include?('create_without_callbacks') || private_instance_methods.include?(:create_without_callbacks)
|
42
|
+
alias_method :create_without_custom_method, :create_without_callbacks
|
43
|
+
alias_method :create_without_callbacks, :create_with_custom_method
|
44
|
+
else
|
45
|
+
alias_method_chain :create, :custom_method
|
46
|
+
end
|
42
47
|
# insert after dirty checking in Rails 2.1
|
43
48
|
# in Ruby 1.9 methods names are returned as symbols
|
44
49
|
if private_instance_methods.include?('update_without_dirty') || private_instance_methods.include?(:update_without_dirty)
|
45
50
|
alias_method :update_without_custom_method, :update_without_dirty
|
46
51
|
alias_method :update_without_dirty, :update_with_custom_method
|
52
|
+
elsif private_instance_methods.include?('update_without_callbacks') || private_instance_methods.include?(:update_without_callbacks)
|
53
|
+
alias_method :update_without_custom_method, :update_without_callbacks
|
54
|
+
alias_method :update_without_callbacks, :update_with_custom_method
|
47
55
|
else
|
48
56
|
alias_method_chain :update, :custom_method
|
49
57
|
end
|
50
58
|
private :create, :update
|
51
|
-
|
59
|
+
if public_instance_methods.include?('destroy_without_callbacks') || public_instance_methods.include?(:destroy_without_callbacks)
|
60
|
+
alias_method :destroy_without_custom_method, :destroy_without_callbacks
|
61
|
+
alias_method :destroy_without_callbacks, :destroy_with_custom_method
|
62
|
+
else
|
63
|
+
alias_method_chain :destroy, :custom_method
|
64
|
+
end
|
52
65
|
public :destroy
|
53
66
|
end
|
54
67
|
end
|
@@ -47,6 +47,17 @@ describe "OracleEnhancedAdapter schema dump" do
|
|
47
47
|
@new_conn = ActiveRecord::Base.oracle_enhanced_connection(CONNECTION_PARAMS)
|
48
48
|
@new_conn.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
|
49
49
|
end
|
50
|
+
|
51
|
+
after(:all) do
|
52
|
+
# Workaround for undefining callback that was defined by JDBC adapter
|
53
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
54
|
+
ActiveRecord::Base.class_eval do
|
55
|
+
def after_save_with_oracle_lob
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
50
61
|
|
51
62
|
unless defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION =~ /^1\.9/
|
52
63
|
it "should return the same tables list as original oracle adapter" do
|
@@ -66,11 +77,11 @@ describe "OracleEnhancedAdapter schema dump" do
|
|
66
77
|
end
|
67
78
|
|
68
79
|
it "should return the same structure dump as original oracle adapter" do
|
69
|
-
@new_conn.structure_dump.should == @old_conn.structure_dump
|
80
|
+
@new_conn.structure_dump.split(";\n\n").sort.should == @old_conn.structure_dump.split(";\n\n").sort
|
70
81
|
end
|
71
82
|
|
72
83
|
it "should return the same structure drop as original oracle adapter" do
|
73
|
-
@new_conn.structure_drop.should == @old_conn.structure_drop
|
84
|
+
@new_conn.structure_drop.split(";\n\n").sort.should == @old_conn.structure_drop.split(";\n\n").sort
|
74
85
|
end
|
75
86
|
end
|
76
87
|
|
@@ -530,14 +541,26 @@ describe "OracleEnhancedAdapter table quoting" do
|
|
530
541
|
end
|
531
542
|
end
|
532
543
|
|
544
|
+
def create_camel_case_table
|
545
|
+
ActiveRecord::Schema.define do
|
546
|
+
suppress_messages do
|
547
|
+
create_table "CamelCase" do |t|
|
548
|
+
t.string :name
|
549
|
+
t.integer :foo
|
550
|
+
end
|
551
|
+
end
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
533
555
|
after(:each) do
|
534
556
|
ActiveRecord::Schema.define do
|
535
557
|
suppress_messages do
|
536
|
-
drop_table "warehouse-things"
|
558
|
+
drop_table "warehouse-things" rescue nil
|
559
|
+
drop_table "CamelCase" rescue nil
|
537
560
|
end
|
538
561
|
end
|
539
|
-
Object.send(:remove_const, "WarehouseThing")
|
540
|
-
|
562
|
+
Object.send(:remove_const, "WarehouseThing") rescue nil
|
563
|
+
Object.send(:remove_const, "CamelCase") rescue nil
|
541
564
|
end
|
542
565
|
|
543
566
|
it "should allow creation of a table with non alphanumeric characters" do
|
@@ -548,6 +571,20 @@ describe "OracleEnhancedAdapter table quoting" do
|
|
548
571
|
|
549
572
|
wh = WarehouseThing.create!(:name => "Foo", :foo => 2)
|
550
573
|
wh.id.should_not be_nil
|
574
|
+
|
575
|
+
@conn.tables.should include("warehouse-things")
|
576
|
+
end
|
577
|
+
|
578
|
+
it "should allow creation of a table with CamelCase name" do
|
579
|
+
create_camel_case_table
|
580
|
+
class ::CamelCase < ActiveRecord::Base
|
581
|
+
set_table_name "CamelCase"
|
582
|
+
end
|
583
|
+
|
584
|
+
cc = CamelCase.create!(:name => "Foo", :foo => 2)
|
585
|
+
cc.id.should_not be_nil
|
586
|
+
|
587
|
+
@conn.tables.should include("CamelCase")
|
551
588
|
end
|
552
589
|
|
553
590
|
end
|
@@ -3,35 +3,101 @@ require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
|
3
3
|
describe "OracleEnhancedAdapter composite_primary_keys support" do
|
4
4
|
|
5
5
|
before(:all) do
|
6
|
-
if defined?(ActiveRecord::ConnectionAdapters::OracleAdapter)
|
7
|
-
@old_oracle_adapter = ActiveRecord::ConnectionAdapters::OracleAdapter
|
8
|
-
ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
|
6
|
+
if defined?(::ActiveRecord::ConnectionAdapters::OracleAdapter)
|
7
|
+
@old_oracle_adapter = ::ActiveRecord::ConnectionAdapters::OracleAdapter
|
8
|
+
::ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
|
9
9
|
end
|
10
10
|
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
set_primary_keys :employee_id, :start_date
|
11
|
+
if $cpk_oracle_adapter
|
12
|
+
::ActiveRecord::ConnectionAdapters::OracleAdapter = $cpk_oracle_adapter
|
13
|
+
$cpk_oracle_adapter = nil
|
15
14
|
end
|
15
|
+
require 'composite_primary_keys'
|
16
16
|
end
|
17
17
|
|
18
18
|
after(:all) do
|
19
|
-
Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
|
20
|
-
|
19
|
+
# Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
|
20
|
+
if defined?(::ActiveRecord::ConnectionAdapters::OracleAdapter)
|
21
|
+
$cpk_oracle_adapter = ::ActiveRecord::ConnectionAdapters::OracleAdapter
|
22
|
+
::ActiveRecord::ConnectionAdapters.send(:remove_const, :OracleAdapter)
|
23
|
+
end
|
21
24
|
if @old_oracle_adapter
|
22
|
-
ActiveRecord::ConnectionAdapters
|
23
|
-
|
25
|
+
::ActiveRecord::ConnectionAdapters::OracleAdapter = @old_oracle_adapter
|
26
|
+
@old_oracle_adapter = nil
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
+
describe "do not use count distinct" do
|
31
|
+
before(:all) do
|
32
|
+
class ::JobHistory < ActiveRecord::Base
|
33
|
+
set_table_name "job_history"
|
34
|
+
set_primary_keys :employee_id, :start_date
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
after(:all) do
|
39
|
+
Object.send(:remove_const, 'JobHistory') if defined?(JobHistory)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should tell ActiveRecord that count distinct is not supported" do
|
43
|
+
ActiveRecord::Base.connection.supports_count_distinct?.should be_false
|
44
|
+
end
|
30
45
|
|
31
|
-
|
32
|
-
|
46
|
+
it "should execute correct SQL COUNT DISTINCT statement on table with composite primary keys" do
|
47
|
+
lambda { JobHistory.count(:distinct => true) }.should_not raise_error
|
48
|
+
end
|
33
49
|
end
|
34
50
|
|
51
|
+
describe "table with LOB" do
|
52
|
+
before(:all) do
|
53
|
+
ActiveRecord::Schema.define do
|
54
|
+
suppress_messages do
|
55
|
+
create_table :cpk_write_lobs_test, :primary_key => [:type_category, :date_value], :force => true do |t|
|
56
|
+
t.string :type_category, :limit => 15, :null => false
|
57
|
+
t.date :date_value, :null => false
|
58
|
+
t.text :results, :null => false
|
59
|
+
t.timestamps
|
60
|
+
end
|
61
|
+
create_table :non_cpk_write_lobs_test, :force => true do |t|
|
62
|
+
t.date :date_value, :null => false
|
63
|
+
t.text :results, :null => false
|
64
|
+
t.timestamps
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
class ::CpkWriteLobsTest < ActiveRecord::Base
|
69
|
+
set_table_name 'cpk_write_lobs_test'
|
70
|
+
set_primary_keys :type_category, :date_value
|
71
|
+
end
|
72
|
+
class ::NonCpkWriteLobsTest < ActiveRecord::Base
|
73
|
+
set_table_name 'non_cpk_write_lobs_test'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
after(:all) do
|
78
|
+
ActiveRecord::Schema.define do
|
79
|
+
suppress_messages do
|
80
|
+
drop_table :cpk_write_lobs_test
|
81
|
+
drop_table :non_cpk_write_lobs_test
|
82
|
+
end
|
83
|
+
end
|
84
|
+
Object.send(:remove_const, "CpkWriteLobsTest")
|
85
|
+
Object.send(:remove_const, "NonCpkWriteLobsTest")
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should create new record in table with CPK and LOB" do
|
89
|
+
lambda {
|
90
|
+
CpkWriteLobsTest.create(:type_category => 'AAA', :date_value => Date.today, :results => 'DATA '*10)
|
91
|
+
}.should_not raise_error
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should create new record in table without CPK and with LOB" do
|
95
|
+
lambda {
|
96
|
+
NonCpkWriteLobsTest.create(:date_value => Date.today, :results => 'DATA '*10)
|
97
|
+
}.should_not raise_error
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
35
101
|
# Other testing was done based on composite_primary_keys tests
|
36
102
|
|
37
103
|
end
|
@@ -74,6 +74,13 @@ describe "OracleEnhancedAdapter date type detection based on column names" do
|
|
74
74
|
column.type_cast(Time.now).class.should == Date
|
75
75
|
end
|
76
76
|
|
77
|
+
it "should typecast DateTime value to Date value from DATE column if column name contains 'date' and emulate_dates_by_column_name is true" do
|
78
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
|
79
|
+
columns = @conn.columns('test_employees')
|
80
|
+
column = columns.detect{|c| c.name == "hire_date"}
|
81
|
+
column.type_cast(DateTime.new(1900,1,1)).class.should == Date
|
82
|
+
end
|
83
|
+
|
77
84
|
describe "/ DATE values from ActiveRecord model" do
|
78
85
|
before(:each) do
|
79
86
|
ActiveRecord::Base.connection.clear_types_for_columns
|
@@ -85,9 +92,9 @@ describe "OracleEnhancedAdapter date type detection based on column names" do
|
|
85
92
|
end
|
86
93
|
end
|
87
94
|
|
88
|
-
def create_test_employee
|
89
|
-
@today = Date.new(2008,8,19)
|
90
|
-
@now = Time.local(2008,8,19,17,03,59)
|
95
|
+
def create_test_employee(params={})
|
96
|
+
@today = params[:today] || Date.new(2008,8,19)
|
97
|
+
@now = params[:now] || Time.local(2008,8,19,17,03,59)
|
91
98
|
@employee = TestEmployee.create(
|
92
99
|
:first_name => "First",
|
93
100
|
:last_name => "Last",
|
@@ -114,6 +121,12 @@ describe "OracleEnhancedAdapter date type detection based on column names" do
|
|
114
121
|
@employee.hire_date.class.should == Date
|
115
122
|
end
|
116
123
|
|
124
|
+
it "should return Date value from DATE column with old date value if column name contains 'date' and emulate_dates_by_column_name is true" do
|
125
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
|
126
|
+
create_test_employee(:today => Date.new(1900,1,1))
|
127
|
+
@employee.hire_date.class.should == Date
|
128
|
+
end
|
129
|
+
|
117
130
|
it "should return Time value from DATE column if column name does not contain 'date' and emulate_dates_by_column_name is true" do
|
118
131
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
|
119
132
|
create_test_employee
|
@@ -129,6 +142,15 @@ describe "OracleEnhancedAdapter date type detection based on column names" do
|
|
129
142
|
@employee.hire_date.class.should == Date
|
130
143
|
end
|
131
144
|
|
145
|
+
it "should return Date value from DATE column with old date value if emulate_dates_by_column_name is false but column is defined as date" do
|
146
|
+
class ::TestEmployee < ActiveRecord::Base
|
147
|
+
set_date_columns :hire_date
|
148
|
+
end
|
149
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = false
|
150
|
+
create_test_employee(:today => Date.new(1900,1,1))
|
151
|
+
@employee.hire_date.class.should == Date
|
152
|
+
end
|
153
|
+
|
132
154
|
it "should return Time value from DATE column if emulate_dates_by_column_name is true but column is defined as datetime" do
|
133
155
|
class ::TestEmployee < ActiveRecord::Base
|
134
156
|
set_datetime_columns :hire_date
|
@@ -159,6 +159,26 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
159
159
|
@employee.update_time.should_not be_nil
|
160
160
|
end
|
161
161
|
|
162
|
+
it "should rollback record when exception is raised in after_create callback" do
|
163
|
+
@employee = TestEmployee.new(
|
164
|
+
:first_name => "First",
|
165
|
+
:last_name => "Last",
|
166
|
+
:hire_date => @today
|
167
|
+
)
|
168
|
+
TestEmployee.class_eval { def after_create() raise "Make the transaction rollback" end }
|
169
|
+
begin
|
170
|
+
employees_count = TestEmployee.count
|
171
|
+
@employee.save
|
172
|
+
fail "Did not raise exception"
|
173
|
+
rescue => e
|
174
|
+
e.message.should == "Make the transaction rollback"
|
175
|
+
@employee.id.should == nil
|
176
|
+
TestEmployee.count.should == employees_count
|
177
|
+
ensure
|
178
|
+
TestEmployee.class_eval { remove_method :after_create }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
162
182
|
it "should update record" do
|
163
183
|
@employee = TestEmployee.create(
|
164
184
|
:first_name => "First",
|
@@ -173,6 +193,29 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
173
193
|
@employee.description.should == "Second Last"
|
174
194
|
end
|
175
195
|
|
196
|
+
it "should rollback record when exception is raised in after_update callback" do
|
197
|
+
TestEmployee.class_eval { def after_update() raise "Make the transaction rollback" end }
|
198
|
+
begin
|
199
|
+
@employee = TestEmployee.create(
|
200
|
+
:first_name => "First",
|
201
|
+
:last_name => "Last",
|
202
|
+
:hire_date => @today,
|
203
|
+
:description => "description"
|
204
|
+
)
|
205
|
+
empl_id = @employee.id
|
206
|
+
@employee.reload
|
207
|
+
@employee.first_name = "Second"
|
208
|
+
@employee.save!
|
209
|
+
fail "Did not raise exception"
|
210
|
+
rescue => e
|
211
|
+
e.message.should == "Make the transaction rollback"
|
212
|
+
@employee.reload
|
213
|
+
@employee.first_name.should == "First"
|
214
|
+
ensure
|
215
|
+
TestEmployee.class_eval { remove_method :after_update }
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
176
219
|
it "should not update record if nothing is changed and partial updates are enabled" do
|
177
220
|
return pending("Not in this ActiveRecord version") unless TestEmployee.respond_to?(:partial_updates=)
|
178
221
|
TestEmployee.partial_updates = true
|
@@ -214,6 +257,27 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
214
257
|
TestEmployee.find_by_employee_id(empl_id).should be_nil
|
215
258
|
end
|
216
259
|
|
260
|
+
it "should rollback record when exception is raised in after_desotry callback" do
|
261
|
+
TestEmployee.class_eval { def after_destroy() raise "Make the transaction rollback" end }
|
262
|
+
@employee = TestEmployee.create(
|
263
|
+
:first_name => "First",
|
264
|
+
:last_name => "Last",
|
265
|
+
:hire_date => @today
|
266
|
+
)
|
267
|
+
@employee.reload
|
268
|
+
empl_id = @employee.id
|
269
|
+
begin
|
270
|
+
@employee.destroy
|
271
|
+
fail "Did not raise exception"
|
272
|
+
rescue => e
|
273
|
+
e.message.should == "Make the transaction rollback"
|
274
|
+
@employee.id.should == empl_id
|
275
|
+
TestEmployee.find_by_employee_id(empl_id).should_not be_nil
|
276
|
+
ensure
|
277
|
+
TestEmployee.class_eval { remove_method :after_destroy }
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
217
281
|
it "should log create record" do
|
218
282
|
log_to @buffer
|
219
283
|
# reestablish plsql.connection as log_to might reset existing connection
|
data/spec/spec_helper.rb
CHANGED
@@ -58,28 +58,35 @@ module LoggerSpecHelper
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
DATABASE_NAME = ENV['DATABASE_NAME'] || 'orcl'
|
62
|
+
DATABASE_HOST = ENV['DATABASE_HOST'] || 'localhost'
|
63
|
+
DATABASE_PORT = ENV['DATABASE_PORT'] || 1521
|
64
|
+
DATABASE_USER = ENV['DATABASE_USER'] || 'hr'
|
65
|
+
DATABASE_PASSWORD = ENV['DATABASE_PASSWORD'] || 'hr'
|
66
|
+
DATABASE_SYS_PASSWORD = ENV['DATABASE_SYS_PASSWORD'] || 'admin'
|
67
|
+
|
61
68
|
CONNECTION_PARAMS = {
|
62
69
|
:adapter => "oracle_enhanced",
|
63
|
-
:database =>
|
64
|
-
:host =>
|
65
|
-
:username =>
|
66
|
-
:password =>
|
70
|
+
:database => DATABASE_NAME,
|
71
|
+
:host => DATABASE_HOST,
|
72
|
+
:username => DATABASE_USER,
|
73
|
+
:password => DATABASE_PASSWORD
|
67
74
|
}
|
68
75
|
|
69
76
|
JDBC_CONNECTION_PARAMS = {
|
70
77
|
:adapter => "jdbc",
|
71
78
|
:driver => "oracle.jdbc.driver.OracleDriver",
|
72
|
-
:url => "jdbc:oracle:thin
|
73
|
-
:username =>
|
74
|
-
:password =>
|
79
|
+
:url => "jdbc:oracle:thin:@#{DATABASE_HOST}:#{DATABASE_PORT}:#{DATABASE_NAME}",
|
80
|
+
:username => DATABASE_USER,
|
81
|
+
:password => DATABASE_PASSWORD
|
75
82
|
}
|
76
83
|
|
77
84
|
SYS_CONNECTION_PARAMS = {
|
78
85
|
:adapter => "oracle_enhanced",
|
79
|
-
:database =>
|
80
|
-
:host =>
|
86
|
+
:database => DATABASE_NAME,
|
87
|
+
:host => DATABASE_HOST,
|
81
88
|
:username => "sys",
|
82
|
-
:password =>
|
89
|
+
:password => DATABASE_SYS_PASSWORD,
|
83
90
|
:privilege => "SYSDBA"
|
84
91
|
}
|
85
92
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-oracle_enhanced-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Raimonds Simanovskis
|
@@ -9,9 +9,29 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-06-08 00:00:00 +03:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.0.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: newgem
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.3.0
|
34
|
+
version:
|
15
35
|
- !ruby/object:Gem::Dependency
|
16
36
|
name: hoe
|
17
37
|
type: :development
|
@@ -20,11 +40,21 @@ dependencies:
|
|
20
40
|
requirements:
|
21
41
|
- - ">="
|
22
42
|
- !ruby/object:Gem::Version
|
23
|
-
version: 1.8.
|
43
|
+
version: 1.8.0
|
24
44
|
version:
|
25
|
-
description:
|
45
|
+
description: |-
|
46
|
+
Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases
|
47
|
+
from Rails which are extracted from current real projects' monkey patches of original Oracle adapter.
|
48
|
+
|
49
|
+
See http://github.com/rsim/oracle-enhanced/wikis for more information.
|
50
|
+
|
51
|
+
For questions and feature discussion please use http://groups.google.com/group/oracle-enhanced
|
52
|
+
|
53
|
+
Blog posts about oracle-enahnced can be found at http://blog.rayapps.com/category/oracle-enhanced
|
54
|
+
|
55
|
+
Bugs and enhancement requests can be reported at http://rsim.lighthouseapp.com/projects/11468-oracle-enhanced
|
26
56
|
email:
|
27
|
-
-
|
57
|
+
- raimonds.simanovskis@gmail.com
|
28
58
|
executables: []
|
29
59
|
|
30
60
|
extensions: []
|
@@ -32,11 +62,11 @@ extensions: []
|
|
32
62
|
extra_rdoc_files:
|
33
63
|
- History.txt
|
34
64
|
- License.txt
|
35
|
-
- README.
|
65
|
+
- README.rdoc
|
36
66
|
files:
|
37
67
|
- History.txt
|
38
68
|
- License.txt
|
39
|
-
- README.
|
69
|
+
- README.rdoc
|
40
70
|
- lib/active_record/connection_adapters/emulation/oracle_adapter.rb
|
41
71
|
- lib/active_record/connection_adapters/oracle_enhanced.rake
|
42
72
|
- lib/active_record/connection_adapters/oracle_enhanced_adapter.rb
|
@@ -61,11 +91,13 @@ files:
|
|
61
91
|
- spec/spec.opts
|
62
92
|
- spec/spec_helper.rb
|
63
93
|
has_rdoc: true
|
64
|
-
homepage: http://oracle-enhanced
|
65
|
-
|
94
|
+
homepage: http://rubyforge.org/projects/oracle-enhanced/
|
95
|
+
licenses: []
|
96
|
+
|
97
|
+
post_install_message:
|
66
98
|
rdoc_options:
|
67
99
|
- --main
|
68
|
-
- README.
|
100
|
+
- README.rdoc
|
69
101
|
require_paths:
|
70
102
|
- lib
|
71
103
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -83,9 +115,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
115
|
requirements: []
|
84
116
|
|
85
117
|
rubyforge_project: oracle-enhanced
|
86
|
-
rubygems_version: 1.3.
|
118
|
+
rubygems_version: 1.3.3
|
87
119
|
signing_key:
|
88
|
-
specification_version:
|
120
|
+
specification_version: 3
|
89
121
|
summary: Oracle enhaced adapter for Active Record
|
90
122
|
test_files: []
|
91
123
|
|