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
data/Rakefile
CHANGED
@@ -21,7 +21,7 @@ EOS
|
|
21
21
|
gem.email = "raimonds.simanovskis@gmail.com"
|
22
22
|
gem.homepage = "http://github.com/rsim/oracle-enhanced"
|
23
23
|
gem.authors = ["Raimonds Simanovskis"]
|
24
|
-
gem.extra_rdoc_files = ['README.
|
24
|
+
gem.extra_rdoc_files = ['README.md']
|
25
25
|
end
|
26
26
|
Jeweler::RubygemsDotOrgTasks.new
|
27
27
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0
|
@@ -5,25 +5,25 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{activerecord-oracle_enhanced-adapter}
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Raimonds Simanovskis"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-08-09}
|
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
|
}
|
16
16
|
s.email = %q{raimonds.simanovskis@gmail.com}
|
17
17
|
s.extra_rdoc_files = [
|
18
|
-
"README.
|
18
|
+
"README.md"
|
19
19
|
]
|
20
20
|
s.files = [
|
21
21
|
".rspec",
|
22
22
|
"Gemfile",
|
23
23
|
"History.txt",
|
24
24
|
"License.txt",
|
25
|
-
"README.
|
26
|
-
"RUNNING_TESTS.
|
25
|
+
"README.md",
|
26
|
+
"RUNNING_TESTS.md",
|
27
27
|
"Rakefile",
|
28
28
|
"VERSION",
|
29
29
|
"activerecord-oracle_enhanced-adapter.gemspec",
|
@@ -66,7 +66,7 @@ This adapter is superset of original ActiveRecord Oracle adapter.
|
|
66
66
|
]
|
67
67
|
s.homepage = %q{http://github.com/rsim/oracle-enhanced}
|
68
68
|
s.require_paths = ["lib"]
|
69
|
-
s.rubygems_version = %q{1.
|
69
|
+
s.rubygems_version = %q{1.6.2}
|
70
70
|
s.summary = %q{Oracle enhanced adapter for ActiveRecord}
|
71
71
|
s.test_files = [
|
72
72
|
"spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb",
|
@@ -97,7 +97,6 @@ This adapter is superset of original ActiveRecord Oracle adapter.
|
|
97
97
|
s.add_development_dependency(%q<actionpack>, [">= 0"])
|
98
98
|
s.add_development_dependency(%q<railties>, [">= 0"])
|
99
99
|
s.add_development_dependency(%q<arel>, [">= 0"])
|
100
|
-
s.add_development_dependency(%q<rack>, [">= 0"])
|
101
100
|
s.add_development_dependency(%q<ruby-plsql>, [">= 0.4.4"])
|
102
101
|
s.add_development_dependency(%q<ruby-oci8>, ["~> 2.0.4"])
|
103
102
|
else
|
@@ -109,7 +108,6 @@ This adapter is superset of original ActiveRecord Oracle adapter.
|
|
109
108
|
s.add_dependency(%q<actionpack>, [">= 0"])
|
110
109
|
s.add_dependency(%q<railties>, [">= 0"])
|
111
110
|
s.add_dependency(%q<arel>, [">= 0"])
|
112
|
-
s.add_dependency(%q<rack>, [">= 0"])
|
113
111
|
s.add_dependency(%q<ruby-plsql>, [">= 0.4.4"])
|
114
112
|
s.add_dependency(%q<ruby-oci8>, ["~> 2.0.4"])
|
115
113
|
end
|
@@ -122,7 +120,6 @@ This adapter is superset of original ActiveRecord Oracle adapter.
|
|
122
120
|
s.add_dependency(%q<actionpack>, [">= 0"])
|
123
121
|
s.add_dependency(%q<railties>, [">= 0"])
|
124
122
|
s.add_dependency(%q<arel>, [">= 0"])
|
125
|
-
s.add_dependency(%q<rack>, [">= 0"])
|
126
123
|
s.add_dependency(%q<ruby-plsql>, [">= 0.4.4"])
|
127
124
|
s.add_dependency(%q<ruby-oci8>, ["~> 2.0.4"])
|
128
125
|
end
|
@@ -15,6 +15,39 @@ def redefine_task(*args, &block)
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
# Creates database user with db:create
|
19
|
+
def create_database_with_oracle_enhanced(config)
|
20
|
+
if config['adapter'] == 'oracle_enhanced'
|
21
|
+
print "Please provide the SYSTEM password for your oracle installation\n>"
|
22
|
+
system_password = $stdin.gets.strip
|
23
|
+
ActiveRecord::Base.establish_connection(config.merge('username' => 'SYSTEM', 'password' => system_password))
|
24
|
+
ActiveRecord::Base.connection.execute "DROP USER #{config['username']} CASCADE" rescue nil
|
25
|
+
ActiveRecord::Base.connection.execute "CREATE USER #{config['username']} IDENTIFIED BY #{config['password']}"
|
26
|
+
ActiveRecord::Base.connection.execute "GRANT unlimited tablespace TO #{config['username']}"
|
27
|
+
ActiveRecord::Base.connection.execute "GRANT create session TO #{config['username']}"
|
28
|
+
ActiveRecord::Base.connection.execute "GRANT create table TO #{config['username']}"
|
29
|
+
ActiveRecord::Base.connection.execute "GRANT create sequence TO #{config['username']}"
|
30
|
+
else
|
31
|
+
create_database_without_oracle_enhanced(config)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
alias :create_database_without_oracle_enhanced :create_database
|
35
|
+
alias :create_database :create_database_with_oracle_enhanced
|
36
|
+
|
37
|
+
# Drops database user with db:drop
|
38
|
+
def drop_database_with_oracle_enhanced(config)
|
39
|
+
if config['adapter'] == 'oracle_enhanced'
|
40
|
+
print "Please provide the SYSTEM password for your oracle installation\n>"
|
41
|
+
system_password = $stdin.gets.strip
|
42
|
+
ActiveRecord::Base.establish_connection(config.merge('username' => 'SYSTEM', 'password' => system_password))
|
43
|
+
ActiveRecord::Base.connection.execute "DROP USER #{config['username']} CASCADE"
|
44
|
+
else
|
45
|
+
drop_database_without_oracle_enhanced(config)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
alias :drop_database_without_oracle_enhanced :drop_database
|
49
|
+
alias :drop_database :drop_database_with_oracle_enhanced
|
50
|
+
|
18
51
|
namespace :db do
|
19
52
|
|
20
53
|
namespace :structure do
|
@@ -53,6 +86,7 @@ namespace :db do
|
|
53
86
|
if abcs['test']['adapter'] == 'oracle_enhanced'
|
54
87
|
ActiveRecord::Base.establish_connection(:test)
|
55
88
|
ActiveRecord::Base.connection.execute_structure_dump(ActiveRecord::Base.connection.full_drop)
|
89
|
+
ActiveRecord::Base.connection.execute("PURGE RECYCLEBIN") rescue nil
|
56
90
|
else
|
57
91
|
Array(existing_actions).each{|action| action.call}
|
58
92
|
end
|
@@ -131,6 +131,19 @@ module ActiveRecord
|
|
131
131
|
# that Date columns are explicily defined with +set_date_columns+ method.
|
132
132
|
cattr_accessor :emulate_dates
|
133
133
|
self.emulate_dates = false
|
134
|
+
|
135
|
+
##
|
136
|
+
# :singleton-method:
|
137
|
+
# OracleEnhancedAdapter will use the default tablespace, but if you want specific types of
|
138
|
+
# objects to go into specific tablespaces, specify them like this in an initializer:
|
139
|
+
#
|
140
|
+
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces =
|
141
|
+
# {:clob => 'TS_LOB', :blob => 'TS_LOB', :index => 'TS_INDEX', :table => 'TS_DATA'}
|
142
|
+
#
|
143
|
+
# Using the :tablespace option where available (e.g create_table) will take precedence
|
144
|
+
# over these settings.
|
145
|
+
cattr_accessor :default_tablespaces
|
146
|
+
self.default_tablespaces={}
|
134
147
|
|
135
148
|
##
|
136
149
|
# :singleton-method:
|
@@ -229,6 +242,10 @@ module ActiveRecord
|
|
229
242
|
@enable_dbms_output = false
|
230
243
|
end
|
231
244
|
|
245
|
+
def self.visitor_for(pool) # :nodoc:
|
246
|
+
Arel::Visitors::Oracle.new(pool)
|
247
|
+
end
|
248
|
+
|
232
249
|
ADAPTER_NAME = 'OracleEnhanced'.freeze
|
233
250
|
|
234
251
|
def adapter_name #:nodoc:
|
@@ -285,7 +302,8 @@ module ActiveRecord
|
|
285
302
|
:time => { :name => "DATE" },
|
286
303
|
:date => { :name => "DATE" },
|
287
304
|
:binary => { :name => "BLOB" },
|
288
|
-
:boolean => { :name => "NUMBER", :limit => 1 }
|
305
|
+
:boolean => { :name => "NUMBER", :limit => 1 },
|
306
|
+
:raw => { :name => "RAW", :limit => 2000 }
|
289
307
|
}
|
290
308
|
# if emulate_booleans_from_strings then store booleans in VARCHAR2
|
291
309
|
NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS = NATIVE_DATABASE_TYPES.dup.merge(
|
@@ -324,30 +342,42 @@ module ActiveRecord
|
|
324
342
|
def in_clause_length
|
325
343
|
1000
|
326
344
|
end
|
345
|
+
alias ids_in_list_limit in_clause_length
|
327
346
|
|
328
347
|
# QUOTING ==================================================
|
329
348
|
#
|
330
349
|
# see: abstract/quoting.rb
|
331
350
|
|
332
351
|
def quote_column_name(name) #:nodoc:
|
333
|
-
# camelCase column names need to be quoted; not that anyone using Oracle
|
334
|
-
# would really do this, but handling this case means we pass the test...
|
335
352
|
name = name.to_s
|
336
353
|
@quoted_column_names[name] ||= begin
|
337
|
-
|
338
|
-
|
339
|
-
when /^[a-z][a-z_0-9\$#]*$/
|
354
|
+
# if only valid lowercase column characters in name
|
355
|
+
if name =~ /\A[a-z][a-z_0-9\$#]*\Z/
|
340
356
|
"\"#{name.upcase}\""
|
341
|
-
when /^[a-z][a-z_0-9\$#\-]*$/i
|
342
|
-
"\"#{name}\""
|
343
|
-
# if other characters present then assume that it is expression
|
344
|
-
# which should not be quoted
|
345
357
|
else
|
346
|
-
|
358
|
+
# remove double quotes which cannot be used inside quoted identifier
|
359
|
+
"\"#{name.gsub('"', '')}\""
|
347
360
|
end
|
348
361
|
end
|
349
362
|
end
|
350
363
|
|
364
|
+
# This method is used in add_index to identify either column name (which is quoted)
|
365
|
+
# or function based index (in which case function expression is not quoted)
|
366
|
+
def quote_column_name_or_expression(name) #:nodoc:
|
367
|
+
name = name.to_s
|
368
|
+
case name
|
369
|
+
# if only valid lowercase column characters in name
|
370
|
+
when /^[a-z][a-z_0-9\$#]*$/
|
371
|
+
"\"#{name.upcase}\""
|
372
|
+
when /^[a-z][a-z_0-9\$#\-]*$/i
|
373
|
+
"\"#{name}\""
|
374
|
+
# if other characters present then assume that it is expression
|
375
|
+
# which should not be quoted
|
376
|
+
else
|
377
|
+
name
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
351
381
|
# Names must be from 1 to 30 bytes long with these exceptions:
|
352
382
|
# * Names of databases are limited to 8 bytes.
|
353
383
|
# * Names of database links can be as long as 128 bytes.
|
@@ -395,6 +425,8 @@ module ActiveRecord
|
|
395
425
|
# NLS_DATE_FORMAT independent DATE support
|
396
426
|
when :date, :time, :datetime
|
397
427
|
quote_date_with_to_date(value)
|
428
|
+
when :raw
|
429
|
+
quote_raw(value)
|
398
430
|
when :string
|
399
431
|
# NCHAR and NVARCHAR2 literals should be quoted with N'...'.
|
400
432
|
# Read directly instance variable as otherwise migrations with table column default values are failing
|
@@ -429,12 +461,45 @@ module ActiveRecord
|
|
429
461
|
"TO_DATE('#{value}','YYYY-MM-DD HH24:MI:SS')"
|
430
462
|
end
|
431
463
|
|
464
|
+
# Encode a string or byte array as string of hex codes
|
465
|
+
def self.encode_raw(value)
|
466
|
+
# When given a string, convert to a byte array.
|
467
|
+
value = value.unpack('C*') if value.is_a?(String)
|
468
|
+
value.map { |x| "%02X" % x }.join
|
469
|
+
end
|
470
|
+
|
471
|
+
# quote encoded raw value
|
472
|
+
def quote_raw(value) #:nodoc:
|
473
|
+
"'#{self.class.encode_raw(value)}'"
|
474
|
+
end
|
475
|
+
|
432
476
|
def quote_timestamp_with_to_timestamp(value) #:nodoc:
|
433
477
|
# add up to 9 digits of fractional seconds to inserted time
|
434
478
|
value = "#{quoted_date(value)}:#{("%.6f"%value.to_f).split('.')[1]}" if value.acts_like?(:time)
|
435
479
|
"TO_TIMESTAMP('#{value}','YYYY-MM-DD HH24:MI:SS:FF6')"
|
436
480
|
end
|
437
481
|
|
482
|
+
# Cast a +value+ to a type that the database understands.
|
483
|
+
def type_cast(value, column)
|
484
|
+
case value
|
485
|
+
when true, false
|
486
|
+
if emulate_booleans_from_strings || column && column.type == :string
|
487
|
+
self.class.boolean_to_string(value)
|
488
|
+
else
|
489
|
+
value ? 1 : 0
|
490
|
+
end
|
491
|
+
when Date, Time
|
492
|
+
if value.acts_like?(:time)
|
493
|
+
zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
|
494
|
+
value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
|
495
|
+
else
|
496
|
+
value
|
497
|
+
end
|
498
|
+
else
|
499
|
+
super
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
438
503
|
# CONNECTION MANAGEMENT ====================================
|
439
504
|
#
|
440
505
|
|
@@ -493,8 +558,8 @@ module ActiveRecord
|
|
493
558
|
log(sql, name) { @connection.exec(sql) }
|
494
559
|
end
|
495
560
|
|
496
|
-
def
|
497
|
-
Arel.sql(":a#{
|
561
|
+
def substitute_at(column, index)
|
562
|
+
Arel.sql(":a#{index + 1}")
|
498
563
|
end
|
499
564
|
|
500
565
|
def clear_cache!
|
@@ -505,7 +570,7 @@ module ActiveRecord
|
|
505
570
|
end
|
506
571
|
|
507
572
|
def exec_query(sql, name = 'SQL', binds = [])
|
508
|
-
log(sql, name) do
|
573
|
+
log(sql, name, binds) do
|
509
574
|
cursor = nil
|
510
575
|
cached = false
|
511
576
|
if binds.empty?
|
@@ -517,10 +582,11 @@ module ActiveRecord
|
|
517
582
|
|
518
583
|
cursor = @statements[sql]
|
519
584
|
|
520
|
-
binds
|
521
|
-
col
|
585
|
+
binds.each_with_index do |bind, i|
|
586
|
+
col, val = bind
|
587
|
+
cursor.bind_param(i + 1, type_cast(val, col), col && col.type)
|
522
588
|
end
|
523
|
-
|
589
|
+
|
524
590
|
cached = true
|
525
591
|
end
|
526
592
|
|
@@ -570,6 +636,69 @@ module ActiveRecord
|
|
570
636
|
end
|
571
637
|
protected :insert_sql
|
572
638
|
|
639
|
+
# New method in ActiveRecord 3.1
|
640
|
+
# Will add RETURNING clause in case of trigger generated primary keys
|
641
|
+
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
642
|
+
unless id_value || pk.nil?
|
643
|
+
sql = "#{sql} RETURNING #{quote_column_name(pk)} INTO :returning_id"
|
644
|
+
(binds = binds.dup) << [:returning_id, nil]
|
645
|
+
end
|
646
|
+
[sql, binds]
|
647
|
+
end
|
648
|
+
|
649
|
+
EXEC_INSERT_RESULT_COLUMNS = %w(returning_id) #:nodoc:
|
650
|
+
|
651
|
+
# New method in ActiveRecord 3.1
|
652
|
+
def exec_insert(sql, name, binds)
|
653
|
+
log(sql, name, binds) do
|
654
|
+
returning_id_index = nil
|
655
|
+
cursor = if @statements.key?(sql)
|
656
|
+
@statements[sql]
|
657
|
+
else
|
658
|
+
@statements[sql] = @connection.prepare(sql)
|
659
|
+
end
|
660
|
+
|
661
|
+
binds.each_with_index do |bind, i|
|
662
|
+
col, val = bind
|
663
|
+
if col == :returning_id
|
664
|
+
returning_id_index = i + 1
|
665
|
+
cursor.bind_returning_param(returning_id_index, Integer)
|
666
|
+
else
|
667
|
+
cursor.bind_param(i + 1, type_cast(val, col), col && col.type)
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
cursor.exec_update
|
672
|
+
|
673
|
+
rows = []
|
674
|
+
if returning_id_index
|
675
|
+
returning_id = cursor.get_returning_param(returning_id_index, Integer)
|
676
|
+
rows << [returning_id]
|
677
|
+
end
|
678
|
+
ActiveRecord::Result.new(EXEC_INSERT_RESULT_COLUMNS, rows)
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
# New method in ActiveRecord 3.1
|
683
|
+
def exec_update(sql, name, binds)
|
684
|
+
log(sql, name, binds) do
|
685
|
+
cursor = if @statements.key?(sql)
|
686
|
+
@statements[sql]
|
687
|
+
else
|
688
|
+
@statements[sql] = @connection.prepare(sql)
|
689
|
+
end
|
690
|
+
|
691
|
+
binds.each_with_index do |bind, i|
|
692
|
+
col, val = bind
|
693
|
+
cursor.bind_param(i + 1, type_cast(val, col), col && col.type)
|
694
|
+
end
|
695
|
+
|
696
|
+
cursor.exec_update
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
alias :exec_delete :exec_update
|
701
|
+
|
573
702
|
# use in set_sequence_name to avoid fetching primary key value from sequence
|
574
703
|
AUTOGENERATED_SEQUENCE_NAME = 'autogenerated'.freeze
|
575
704
|
|
@@ -617,11 +746,11 @@ module ActiveRecord
|
|
617
746
|
limit = options[:limit]
|
618
747
|
limit = limit.is_a?(String) && limit.blank? ? nil : limit && limit.to_i
|
619
748
|
if limit && offset > 0
|
620
|
-
sql.replace "
|
749
|
+
sql.replace "SELECT * FROM (SELECT raw_sql_.*, ROWNUM raw_rnum_ FROM (#{sql}) raw_sql_ WHERE ROWNUM <= #{offset+limit}) WHERE raw_rnum_ > #{offset}"
|
621
750
|
elsif limit
|
622
|
-
sql.replace "
|
751
|
+
sql.replace "SELECT * FROM (#{sql}) WHERE ROWNUM <= #{limit}"
|
623
752
|
elsif offset > 0
|
624
|
-
sql.replace "
|
753
|
+
sql.replace "SELECT * FROM (SELECT raw_sql_.*, ROWNUM raw_rnum_ FROM (#{sql}) raw_sql_) WHERE raw_rnum_ > #{offset}"
|
625
754
|
end
|
626
755
|
end
|
627
756
|
|
@@ -630,7 +759,16 @@ module ActiveRecord
|
|
630
759
|
# Returns true for Oracle adapter (since Oracle requires primary key
|
631
760
|
# values to be pre-fetched before insert). See also #next_sequence_value.
|
632
761
|
def prefetch_primary_key?(table_name = nil)
|
633
|
-
|
762
|
+
return true if table_name.nil?
|
763
|
+
table_name = table_name.to_s
|
764
|
+
do_not_prefetch = @@do_not_prefetch_primary_key[table_name]
|
765
|
+
if do_not_prefetch.nil?
|
766
|
+
owner, desc_table_name, db_link = @connection.describe(table_name)
|
767
|
+
@@do_not_prefetch_primary_key[table_name] = do_not_prefetch =
|
768
|
+
!has_primary_key?(table_name, owner, desc_table_name, db_link) ||
|
769
|
+
has_primary_key_trigger?(table_name, owner, desc_table_name, db_link)
|
770
|
+
end
|
771
|
+
!do_not_prefetch
|
634
772
|
end
|
635
773
|
|
636
774
|
# used just in tests to clear prefetch primary key flag for all tables
|
@@ -650,7 +788,13 @@ module ActiveRecord
|
|
650
788
|
def insert_fixture(fixture, table_name) #:nodoc:
|
651
789
|
super
|
652
790
|
|
653
|
-
|
791
|
+
if ActiveRecord::Base.pluralize_table_names
|
792
|
+
klass = table_name.singularize.camelize
|
793
|
+
else
|
794
|
+
klass = table_name.camelize
|
795
|
+
end
|
796
|
+
|
797
|
+
klass = klass.constantize rescue nil
|
654
798
|
if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base)
|
655
799
|
write_lobs(table_name, klass, fixture)
|
656
800
|
end
|
@@ -684,22 +828,22 @@ module ActiveRecord
|
|
684
828
|
|
685
829
|
# Current database name
|
686
830
|
def current_database
|
687
|
-
select_value("
|
831
|
+
select_value("SELECT SYS_CONTEXT('userenv', 'db_name') FROM dual")
|
688
832
|
end
|
689
833
|
|
690
834
|
# Current database session user
|
691
835
|
def current_user
|
692
|
-
select_value("
|
836
|
+
select_value("SELECT SYS_CONTEXT('userenv', 'session_user') FROM dual")
|
693
837
|
end
|
694
838
|
|
695
839
|
# Default tablespace name of current user
|
696
840
|
def default_tablespace
|
697
|
-
select_value("
|
841
|
+
select_value("SELECT LOWER(default_tablespace) FROM user_users WHERE username = SYS_CONTEXT('userenv', 'session_user')")
|
698
842
|
end
|
699
843
|
|
700
844
|
def tables(name = nil) #:nodoc:
|
701
845
|
select_values(
|
702
|
-
"
|
846
|
+
"SELECT DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name) FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N'",
|
703
847
|
name)
|
704
848
|
end
|
705
849
|
|
@@ -712,7 +856,7 @@ module ActiveRecord
|
|
712
856
|
end
|
713
857
|
|
714
858
|
def materialized_views #:nodoc:
|
715
|
-
select_values("
|
859
|
+
select_values("SELECT LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', 'session_user')")
|
716
860
|
end
|
717
861
|
|
718
862
|
cattr_accessor :all_schema_indexes #:nodoc:
|
@@ -723,7 +867,7 @@ module ActiveRecord
|
|
723
867
|
(owner, table_name, db_link) = @connection.describe(table_name)
|
724
868
|
unless all_schema_indexes
|
725
869
|
default_tablespace_name = default_tablespace
|
726
|
-
result = select_all(<<-SQL)
|
870
|
+
result = select_all(<<-SQL.strip.gsub(/\s+/, ' '))
|
727
871
|
SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
|
728
872
|
i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
|
729
873
|
LOWER(i.tablespace_name) AS tablespace_name,
|
@@ -749,13 +893,16 @@ module ActiveRecord
|
|
749
893
|
statement_parameters = nil
|
750
894
|
if row['index_type'] == 'DOMAIN' && row['ityp_owner'] == 'CTXSYS' && row['ityp_name'] == 'CONTEXT'
|
751
895
|
procedure_name = default_datastore_procedure(row['index_name'])
|
752
|
-
|
753
|
-
SELECT
|
896
|
+
source = select_values(<<-SQL).join
|
897
|
+
SELECT text
|
754
898
|
FROM all_source#{db_link}
|
755
899
|
WHERE owner = '#{owner}'
|
756
900
|
AND name = '#{procedure_name.upcase}'
|
757
|
-
|
901
|
+
ORDER BY line
|
758
902
|
SQL
|
903
|
+
if source =~ /-- add_context_index_parameters (.+)\n/
|
904
|
+
statement_parameters = $1
|
905
|
+
end
|
759
906
|
end
|
760
907
|
all_schema_indexes << OracleEnhancedIndexDefinition.new(row['table_name'], row['index_name'],
|
761
908
|
row['uniqueness'] == "UNIQUE", row['index_type'] == 'DOMAIN' ? "#{row['ityp_owner']}.#{row['ityp_name']}" : nil,
|
@@ -855,22 +1002,23 @@ module ActiveRecord
|
|
855
1002
|
|
856
1003
|
(owner, desc_table_name, db_link) = @connection.describe(table_name)
|
857
1004
|
|
858
|
-
|
859
|
-
|
860
|
-
has_primary_key_trigger?(table_name, owner, desc_table_name, db_link)
|
1005
|
+
# reset do_not_prefetch_primary_key cache for this table
|
1006
|
+
@@do_not_prefetch_primary_key[table_name] = nil
|
861
1007
|
|
862
|
-
table_cols = <<-SQL
|
863
|
-
|
864
|
-
|
1008
|
+
table_cols = <<-SQL.strip.gsub(/\s+/, ' ')
|
1009
|
+
SELECT column_name AS name, data_type AS sql_type, data_default, nullable, virtual_column, hidden_column,
|
1010
|
+
DECODE(data_type, 'NUMBER', data_precision,
|
865
1011
|
'FLOAT', data_precision,
|
866
|
-
'VARCHAR2',
|
867
|
-
'
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
1012
|
+
'VARCHAR2', DECODE(char_used, 'C', char_length, data_length),
|
1013
|
+
'RAW', DECODE(char_used, 'C', char_length, data_length),
|
1014
|
+
'CHAR', DECODE(char_used, 'C', char_length, data_length),
|
1015
|
+
NULL) AS limit,
|
1016
|
+
DECODE(data_type, 'NUMBER', data_scale, NULL) AS scale
|
1017
|
+
FROM all_tab_cols#{db_link}
|
1018
|
+
WHERE owner = '#{owner}'
|
1019
|
+
AND table_name = '#{desc_table_name}'
|
1020
|
+
AND hidden_column = 'NO'
|
1021
|
+
ORDER BY column_id
|
874
1022
|
SQL
|
875
1023
|
|
876
1024
|
# added deletion of ignored columns
|
@@ -899,7 +1047,7 @@ module ActiveRecord
|
|
899
1047
|
# pass table name for table specific column definitions
|
900
1048
|
table_name,
|
901
1049
|
# pass column type if specified in class definition
|
902
|
-
get_type_for_column(table_name, oracle_downcase(row['name'])))
|
1050
|
+
get_type_for_column(table_name, oracle_downcase(row['name'])), row['virtual_column']=='YES')
|
903
1051
|
end
|
904
1052
|
end
|
905
1053
|
|
@@ -940,14 +1088,14 @@ module ActiveRecord
|
|
940
1088
|
(owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
|
941
1089
|
|
942
1090
|
# changed back from user_constraints to all_constraints for consistency
|
943
|
-
pks = select_values(<<-SQL, 'Primary Key')
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
1091
|
+
pks = select_values(<<-SQL.strip.gsub(/\s+/, ' '), 'Primary Key')
|
1092
|
+
SELECT cc.column_name
|
1093
|
+
FROM all_constraints#{db_link} c, all_cons_columns#{db_link} cc
|
1094
|
+
WHERE c.owner = '#{owner}'
|
1095
|
+
AND c.table_name = '#{desc_table_name}'
|
1096
|
+
AND c.constraint_type = 'P'
|
1097
|
+
AND cc.owner = c.owner
|
1098
|
+
AND cc.constraint_name = c.constraint_name
|
951
1099
|
SQL
|
952
1100
|
|
953
1101
|
# only support single column keys
|
@@ -994,7 +1142,7 @@ module ActiveRecord
|
|
994
1142
|
end
|
995
1143
|
|
996
1144
|
def temporary_table?(table_name) #:nodoc:
|
997
|
-
select_value("
|
1145
|
+
select_value("SELECT temporary FROM user_tables WHERE table_name = '#{table_name.upcase}'") == 'Y'
|
998
1146
|
end
|
999
1147
|
|
1000
1148
|
# ORDER BY clause for the passed order option.
|
@@ -1073,8 +1221,12 @@ module ActiveRecord
|
|
1073
1221
|
end
|
1074
1222
|
|
1075
1223
|
protected
|
1076
|
-
def log(sql, name) #:nodoc:
|
1077
|
-
|
1224
|
+
def log(sql, name, binds = nil) #:nodoc:
|
1225
|
+
if binds
|
1226
|
+
super sql, name, binds
|
1227
|
+
else
|
1228
|
+
super sql, name
|
1229
|
+
end
|
1078
1230
|
ensure
|
1079
1231
|
log_dbms_output if dbms_output_enabled?
|
1080
1232
|
end
|