activerecord-oracle_enhanced-adapter 1.4.3 → 1.5.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -14
- data/History.md +51 -0
- data/README.md +32 -1
- data/VERSION +1 -1
- data/activerecord-oracle_enhanced-adapter.gemspec +2 -4
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +315 -57
- data/lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb +55 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +4 -13
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +5 -6
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +19 -11
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +163 -232
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +18 -10
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +20 -32
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +54 -35
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +5 -74
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +3 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +98 -98
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +5 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +3 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +11 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +56 -55
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +15 -8
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +4 -3
- data/spec/spec_helper.rb +25 -54
- metadata +32 -20
- data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
- data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -121
- data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a74f5a066c9c346da43e6a9d740a3aff47e59ef2
|
4
|
+
data.tar.gz: af9745bc4a32f6d765a5d536d2e13d8a5962eed3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4307827c8682b9654fad38a2cdca95d0a93a864401a09f9e88bc0db787faa825605631c7867635ae26d6e58796a846c9cefa35b2a18a11c2ab5a79cff6ec9b56
|
7
|
+
data.tar.gz: 78cd7ef1859e4a8ac0d2915a66971ff8a45282c8c90284259e39d4d832682876cb1b4f06d9a32135a68652bc3456c6b45f03c243afb675dc029900287d09611d
|
data/Gemfile
CHANGED
@@ -9,18 +9,7 @@ group :development do
|
|
9
9
|
gem 'activerecord', "=#{ENV['RAILS_GEM_VERSION']}"
|
10
10
|
gem 'actionpack', "=#{ENV['RAILS_GEM_VERSION']}"
|
11
11
|
gem 'activesupport', "=#{ENV['RAILS_GEM_VERSION']}"
|
12
|
-
|
13
|
-
when /^2.0/
|
14
|
-
gem 'composite_primary_keys', '=0.9.93'
|
15
|
-
when /^2.1/
|
16
|
-
gem 'composite_primary_keys', '=1.0.8'
|
17
|
-
when /^2.2/
|
18
|
-
gem 'composite_primary_keys', '=2.2.2'
|
19
|
-
when /^2.3.3/
|
20
|
-
gem 'composite_primary_keys', '=2.3.2'
|
21
|
-
when /^3/
|
22
|
-
gem 'railties', "=#{ENV['RAILS_GEM_VERSION']}"
|
23
|
-
end
|
12
|
+
gem 'railties', "=#{ENV['RAILS_GEM_VERSION']}"
|
24
13
|
else
|
25
14
|
%w(activerecord activemodel activesupport actionpack railties).each do |gem_name|
|
26
15
|
if ENV['RAILS_GEM_PATH']
|
@@ -43,10 +32,11 @@ group :development do
|
|
43
32
|
end
|
44
33
|
end
|
45
34
|
|
46
|
-
gem
|
35
|
+
gem "activerecord-deprecated_finders"
|
36
|
+
gem 'ruby-plsql', '>=0.5.0'
|
47
37
|
|
48
38
|
platforms :ruby do
|
49
|
-
gem 'ruby-oci8', '>=2.
|
39
|
+
gem 'ruby-oci8', '>=2.1.2'
|
50
40
|
end
|
51
41
|
|
52
42
|
end
|
data/History.md
CHANGED
@@ -1,3 +1,54 @@
|
|
1
|
+
## 1.5.0.rc1 / 2013-10-28
|
2
|
+
|
3
|
+
* Enhancements and major changes
|
4
|
+
* Support Rails 4.0
|
5
|
+
* Desupport Rails 3.2 and lower version. To support Rails 3.2, use Version 1.4.3
|
6
|
+
* Drop session store support [#219]
|
7
|
+
* Create indexes automatically for references and belongs_to [#183]
|
8
|
+
* Use the index name explicitly provided in a migration when reverting [#296]
|
9
|
+
* Rename indexes when a table or column is renamed [#286]
|
10
|
+
* Support refactored remove_column [#172]
|
11
|
+
* Support allowed_index_name_length method [#285]
|
12
|
+
* Remove schema prefix from sequence name if present before truncating [#155]
|
13
|
+
* Bumped jeweler, ruby-plsql and ruby-oci8 version [#176]
|
14
|
+
* Support also ojdbc6.jar for Java 1.7 [#350]
|
15
|
+
* Support "activerecord-deprecated_finders" [#210]
|
16
|
+
* Prepared statements can be disabled [#295]
|
17
|
+
* Ensure disconnecting or reconnecting resets the transaction state [#220]
|
18
|
+
* Support for specifying transaction isolation level [#226]
|
19
|
+
* Rename the partial_updates config to partial_writes [#234]
|
20
|
+
* Deprecate passing a string as third argument of add_index [#242]
|
21
|
+
* Rename update method to update_record, create method to create_record [#273]
|
22
|
+
* Deprecate #connection in favour of accessing it via the class [#297]
|
23
|
+
* Support SchemaCreation [#298]
|
24
|
+
* Add support for foreign key creation in create_table [#317]
|
25
|
+
* Add virtual columns support for rail4 branch [#329]
|
26
|
+
* Support columns_for_distinct method [#340]
|
27
|
+
* Clear index cache when any table dropped [#200]
|
28
|
+
* Clear index cache when remove_column executed [#269]
|
29
|
+
* Dump schema uses ruby 1.9 style hash [#229]
|
30
|
+
* Support _field_changed? and drop field_changed? [#182 #254]
|
31
|
+
* Use arel nodes instead of raw sql [#198]
|
32
|
+
* Raise an ArgumentError when passing an invalid option to add_index [#242]
|
33
|
+
* Split OracleEnhancedColumnDumper from OracleEnhancedSchemaDumper [#292]
|
34
|
+
* Unit test sets default_timezone = :local [#184]
|
35
|
+
* Support reset_pk_sequence! [#287]
|
36
|
+
|
37
|
+
* Bug Fix
|
38
|
+
* Address ArgumentError: wrong number of arguments (5 for 3) [#166]
|
39
|
+
* Address NoMethodError: undefined method `column_types' [#173]
|
40
|
+
* Schema dumper removes table_name_prefix and table_name_suffix [#191]
|
41
|
+
* Add clear_logger to address ArgumentError: wrong number of arguments (1 for 2) [#193]
|
42
|
+
* Use Relation#to_a as Relation#all is deprecated in Rails [#203]
|
43
|
+
* Address Address test_integer_zero_to_integer_zero_not_marked_as_changed failure [#207]
|
44
|
+
* Address NoMethodError undefined method `default_string' [#221]
|
45
|
+
* Address you can't redefine the primary key column 'id'. To define a custom primary key, pass { id: false } to create_table [#238]
|
46
|
+
* Remove unnecessary DEPRECATION WARNING [#255]
|
47
|
+
* Assigning "0.0" to a nullable numeric column does not make it dirty [#293]
|
48
|
+
|
49
|
+
* Known Issues
|
50
|
+
* Oracle Text features are not fully supported with Oracle 12c [#331]
|
51
|
+
|
1
52
|
### 1.4.3 / 2013-10-24
|
2
53
|
|
3
54
|
* No changes since 1.4.3.rc2
|
data/README.md
CHANGED
@@ -6,11 +6,42 @@ Oracle enhanced adapter for ActiveRecord
|
|
6
6
|
DESCRIPTION
|
7
7
|
-----------
|
8
8
|
|
9
|
-
Oracle enhanced ActiveRecord adapter provides Oracle database access from Ruby on Rails applications. Oracle enhanced adapter can be used from Ruby on Rails versions 2.3.x and
|
9
|
+
Oracle enhanced ActiveRecord adapter provides Oracle database access from Ruby on Rails applications. Oracle enhanced adapter can be used from Ruby on Rails versions between 2.3.x and 4.0 and it is working with Oracle database versions from 10g to 12c.
|
10
10
|
|
11
11
|
INSTALLATION
|
12
12
|
------------
|
13
13
|
|
14
|
+
### Rails 4
|
15
|
+
|
16
|
+
Oracle enhanced adapter version 1.5 just supports Rails 4 and does not support Rails 3.2 or lower version of Rails.
|
17
|
+
|
18
|
+
When using Ruby on Rails version 4 then in Gemfile include
|
19
|
+
|
20
|
+
gem 'activerecord-oracle_enhanced-adapter', '~> 1.5.0'
|
21
|
+
|
22
|
+
where instead of 1.5.0 you can specify any other desired version. It is recommended to specify version with `~>` which means that use specified version or later patch versions (in this example any later 1.5.x version but not 1.6.x version). Oracle enhanced adapter maintains API backwards compatibility during patch version upgrades and therefore it is safe to always upgrade to latest patch version.
|
23
|
+
|
24
|
+
If you would like to use latest adapter version from github then specify
|
25
|
+
|
26
|
+
gem 'activerecord-oracle_enhanced-adapter', :git => 'git://github.com/rsim/oracle-enhanced.git'
|
27
|
+
|
28
|
+
If you are using CRuby 1.9.3 or 2.0 then you need to install ruby-oci8 gem as well as Oracle client, e.g. [Oracle Instant Client](http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html). Include in Gemfile also ruby-oci8:
|
29
|
+
|
30
|
+
gem 'ruby-oci8', '~> 2.1.0'
|
31
|
+
|
32
|
+
If you are using JRuby then you need to download latest [Oracle JDBC driver](http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html) - either ojdbc7.jar or ojdbc6.jar for Java 7, ojdbc6.jar for Java 6 or ojdbc5.jar for Java 5. And copy this file to one of these locations:
|
33
|
+
|
34
|
+
* in `./lib` directory of Rails application
|
35
|
+
* in some directory which is in `PATH`
|
36
|
+
* in `JRUBY_HOME/lib` directory
|
37
|
+
* or include path to JDBC driver jar file in Java `CLASSPATH`
|
38
|
+
|
39
|
+
After specifying necessary gems in Gemfile run
|
40
|
+
|
41
|
+
bundle install
|
42
|
+
|
43
|
+
to install the adapter (or later run `bundle update` to force updating to latest version).
|
44
|
+
|
14
45
|
### Rails 3
|
15
46
|
|
16
47
|
When using Ruby on Rails version 3 then in Gemfile include
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.5.0.beta1
|
@@ -5,7 +5,7 @@
|
|
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.5.0.beta1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = [%q{Raimonds Simanovskis}]
|
@@ -29,10 +29,9 @@ This adapter is superset of original ActiveRecord Oracle adapter.
|
|
29
29
|
"activerecord-oracle_enhanced-adapter.gemspec",
|
30
30
|
"lib/active_record/connection_adapters/emulation/oracle_adapter.rb",
|
31
31
|
"lib/active_record/connection_adapters/oracle_enhanced.rake",
|
32
|
-
"lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb",
|
33
32
|
"lib/active_record/connection_adapters/oracle_enhanced_adapter.rb",
|
34
|
-
"lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb",
|
35
33
|
"lib/active_record/connection_adapters/oracle_enhanced_column.rb",
|
34
|
+
"lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb",
|
36
35
|
"lib/active_record/connection_adapters/oracle_enhanced_connection.rb",
|
37
36
|
"lib/active_record/connection_adapters/oracle_enhanced_context_index.rb",
|
38
37
|
"lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb",
|
@@ -46,7 +45,6 @@ This adapter is superset of original ActiveRecord Oracle adapter.
|
|
46
45
|
"lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb",
|
47
46
|
"lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb",
|
48
47
|
"lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb",
|
49
|
-
"lib/active_record/connection_adapters/oracle_enhanced_tasks.rb",
|
50
48
|
"lib/active_record/connection_adapters/oracle_enhanced_version.rb",
|
51
49
|
"lib/activerecord-oracle_enhanced-adapter.rb",
|
52
50
|
"spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb",
|
@@ -29,18 +29,132 @@
|
|
29
29
|
# contribution.
|
30
30
|
# portions Copyright 2005 Graham Jenkins
|
31
31
|
|
32
|
-
# ActiveRecord 2.2 does not load version file automatically
|
33
|
-
require 'active_record/version' unless defined?(ActiveRecord::VERSION)
|
34
|
-
|
35
32
|
require 'active_record/connection_adapters/abstract_adapter'
|
36
33
|
require 'active_record/connection_adapters/oracle_enhanced_connection'
|
37
34
|
|
38
|
-
require 'active_record/connection_adapters/oracle_enhanced_base_ext'
|
39
35
|
require 'active_record/connection_adapters/oracle_enhanced_column'
|
40
36
|
|
41
37
|
require 'digest/sha1'
|
42
38
|
|
39
|
+
require 'arel/visitors/bind_visitor'
|
40
|
+
|
41
|
+
ActiveRecord::Base.class_eval do
|
42
|
+
class_attribute :custom_create_method, :custom_update_method, :custom_delete_method
|
43
|
+
end
|
44
|
+
|
45
|
+
module ActiveRecord
|
46
|
+
class Base
|
47
|
+
|
48
|
+
# Specify table columns which should be ignored by ActiveRecord, e.g.:
|
49
|
+
#
|
50
|
+
# ignore_table_columns :attribute1, :attribute2
|
51
|
+
def self.ignore_table_columns(*args)
|
52
|
+
connection.ignore_table_columns(table_name,*args)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Specify which table columns should be typecasted to Date (without time), e.g.:
|
56
|
+
#
|
57
|
+
# set_date_columns :created_on, :updated_on
|
58
|
+
def self.set_date_columns(*args)
|
59
|
+
connection.set_type_for_columns(table_name,:date,*args)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Specify which table columns should be typecasted to Time (or DateTime), e.g.:
|
63
|
+
#
|
64
|
+
# set_datetime_columns :created_date, :updated_date
|
65
|
+
def self.set_datetime_columns(*args)
|
66
|
+
connection.set_type_for_columns(table_name,:datetime,*args)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Specify which table columns should be typecasted to boolean values +true+ or +false+, e.g.:
|
70
|
+
#
|
71
|
+
# set_boolean_columns :is_valid, :is_completed
|
72
|
+
def self.set_boolean_columns(*args)
|
73
|
+
connection.set_type_for_columns(table_name,:boolean,*args)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Specify which table columns should be typecasted to integer values.
|
77
|
+
# Might be useful to force NUMBER(1) column to be integer and not boolean, or force NUMBER column without
|
78
|
+
# scale to be retrieved as integer and not decimal. Example:
|
79
|
+
#
|
80
|
+
# set_integer_columns :version_number, :object_identifier
|
81
|
+
def self.set_integer_columns(*args)
|
82
|
+
connection.set_type_for_columns(table_name,:integer,*args)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Specify which table columns should be typecasted to string values.
|
86
|
+
# Might be useful to specify that columns should be string even if its name matches boolean column criteria.
|
87
|
+
#
|
88
|
+
# set_string_columns :active_flag
|
89
|
+
def self.set_string_columns(*args)
|
90
|
+
connection.set_type_for_columns(table_name,:string,*args)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Get table comment from schema definition.
|
94
|
+
def self.table_comment
|
95
|
+
connection.table_comment(self.table_name)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.lob_columns
|
99
|
+
columns.select do |column|
|
100
|
+
column.respond_to?(:lob?) && column.lob?
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.virtual_columns
|
105
|
+
columns.select do |column|
|
106
|
+
column.respond_to?(:virtual?) && column.virtual?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def arel_attributes_with_values(attribute_names)
|
111
|
+
virtual_column_names = self.class.virtual_columns.map(&:name)
|
112
|
+
super(attribute_names - virtual_column_names)
|
113
|
+
end
|
114
|
+
|
115
|
+
# After setting large objects to empty, select the OCI8::LOB
|
116
|
+
# and write back the data.
|
117
|
+
before_update :record_changed_lobs
|
118
|
+
after_update :enhanced_write_lobs
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def enhanced_write_lobs
|
123
|
+
if self.class.connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
|
124
|
+
!(
|
125
|
+
(self.class.custom_create_method || self.class.custom_create_method) ||
|
126
|
+
(self.class.custom_update_method || self.class.custom_update_method)
|
127
|
+
)
|
128
|
+
self.class.connection.write_lobs(self.class.table_name, self.class, attributes, @changed_lob_columns || self.class.lob_columns)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def record_changed_lobs
|
133
|
+
@changed_lob_columns = self.class.lob_columns.select do |col|
|
134
|
+
self.class.serialized_attributes.keys.include?(col.name) ||
|
135
|
+
(self.send(:"#{col.name}_changed?") && !self.class.readonly_attributes.to_a.include?(col.name))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
43
141
|
module ActiveRecord
|
142
|
+
module ConnectionHandling #:nodoc:
|
143
|
+
# Establishes a connection to the database that's used by all Active Record objects.
|
144
|
+
def oracle_enhanced_connection(config) #:nodoc:
|
145
|
+
if config[:emulate_oracle_adapter] == true
|
146
|
+
# allows the enhanced adapter to look like the OracleAdapter. Useful to pick up
|
147
|
+
# conditionals in the rails activerecord test suite
|
148
|
+
require 'active_record/connection_adapters/emulation/oracle_adapter'
|
149
|
+
ConnectionAdapters::OracleAdapter.new(
|
150
|
+
ConnectionAdapters::OracleEnhancedConnection.create(config), logger, config)
|
151
|
+
else
|
152
|
+
ConnectionAdapters::OracleEnhancedAdapter.new(
|
153
|
+
ConnectionAdapters::OracleEnhancedConnection.create(config), logger, config)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
44
158
|
module ConnectionAdapters #:nodoc:
|
45
159
|
|
46
160
|
# Oracle enhanced adapter will work with both
|
@@ -263,13 +377,21 @@ module ActiveRecord
|
|
263
377
|
end
|
264
378
|
end
|
265
379
|
|
380
|
+
class BindSubstitution < Arel::Visitors::Oracle #:nodoc:
|
381
|
+
include Arel::Visitors::BindVisitor
|
382
|
+
end
|
383
|
+
|
266
384
|
def initialize(connection, logger, config) #:nodoc:
|
267
385
|
super(connection, logger)
|
268
386
|
@quoted_column_names, @quoted_table_names = {}, {}
|
269
387
|
@config = config
|
270
388
|
@statements = StatementPool.new(connection, config.fetch(:statement_limit) { 250 })
|
271
389
|
@enable_dbms_output = false
|
272
|
-
|
390
|
+
if config.fetch(:prepared_statements) { true }
|
391
|
+
@visitor = Arel::Visitors::Oracle.new self
|
392
|
+
else
|
393
|
+
@visitor = unprepared_visitor
|
394
|
+
end
|
273
395
|
end
|
274
396
|
|
275
397
|
def self.visitor_for(pool) # :nodoc:
|
@@ -294,6 +416,10 @@ module ActiveRecord
|
|
294
416
|
true
|
295
417
|
end
|
296
418
|
|
419
|
+
def supports_transaction_isolation? #:nodoc:
|
420
|
+
true
|
421
|
+
end
|
422
|
+
|
297
423
|
#:stopdoc:
|
298
424
|
DEFAULT_NLS_PARAMETERS = {
|
299
425
|
:nls_calendar => nil,
|
@@ -360,7 +486,17 @@ module ActiveRecord
|
|
360
486
|
IDENTIFIER_MAX_LENGTH
|
361
487
|
end
|
362
488
|
|
363
|
-
# the maximum length
|
489
|
+
# Returns the maximum allowed length for an index name. This
|
490
|
+
# limit is enforced by rails and Is less than or equal to
|
491
|
+
# <tt>index_name_length</tt>. The gap between
|
492
|
+
# <tt>index_name_length</tt> is to allow internal rails
|
493
|
+
# opreations to use prefixes in temporary opreations.
|
494
|
+
def allowed_index_name_length
|
495
|
+
index_name_length
|
496
|
+
end
|
497
|
+
|
498
|
+
# the maximum length of an index name
|
499
|
+
# supported by this database
|
364
500
|
def index_name_length
|
365
501
|
IDENTIFIER_MAX_LENGTH
|
366
502
|
end
|
@@ -451,7 +587,7 @@ module ActiveRecord
|
|
451
587
|
if value && column
|
452
588
|
case column.type
|
453
589
|
when :text, :binary
|
454
|
-
%Q{empty_#{ column.
|
590
|
+
%Q{empty_#{ type_to_sql(column.type.to_sym).downcase rescue 'blob' }()}
|
455
591
|
# NLS_DATE_FORMAT independent TIMESTAMP support
|
456
592
|
when :timestamp
|
457
593
|
quote_timestamp_with_to_timestamp(value)
|
@@ -565,7 +701,7 @@ module ActiveRecord
|
|
565
701
|
|
566
702
|
# Reconnects to the database.
|
567
703
|
def reconnect! #:nodoc:
|
568
|
-
|
704
|
+
super
|
569
705
|
@connection.reset!
|
570
706
|
rescue OracleEnhancedConnectionException => e
|
571
707
|
@logger.warn "#{adapter_name} automatic reconnection failed: #{e.message}" if @logger
|
@@ -578,7 +714,7 @@ module ActiveRecord
|
|
578
714
|
|
579
715
|
# Disconnects from the database.
|
580
716
|
def disconnect! #:nodoc:
|
581
|
-
|
717
|
+
super
|
582
718
|
@connection.logoff rescue nil
|
583
719
|
end
|
584
720
|
|
@@ -650,7 +786,7 @@ module ActiveRecord
|
|
650
786
|
end
|
651
787
|
|
652
788
|
def explain(arel, binds = [])
|
653
|
-
sql = "EXPLAIN PLAN FOR #{to_sql(arel)}"
|
789
|
+
sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
|
654
790
|
return if sql =~ /FROM all_/
|
655
791
|
if ORACLE_ENHANCED_CONNECTION == :jdbc
|
656
792
|
exec_query(sql, 'EXPLAIN', binds)
|
@@ -699,7 +835,7 @@ module ActiveRecord
|
|
699
835
|
end
|
700
836
|
|
701
837
|
# New method in ActiveRecord 3.1
|
702
|
-
def exec_insert(sql, name, binds)
|
838
|
+
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
703
839
|
log(sql, name, binds) do
|
704
840
|
returning_id_col = returning_id_index = nil
|
705
841
|
cursor = if @statements.key?(sql)
|
@@ -775,6 +911,21 @@ module ActiveRecord
|
|
775
911
|
@connection.autocommit = false
|
776
912
|
end
|
777
913
|
|
914
|
+
def transaction_isolation_levels
|
915
|
+
# Oracle database supports `READ COMMITTED` and `SERIALIZABLE`
|
916
|
+
# No read uncommitted nor repeatable read supppoted
|
917
|
+
# http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10005.htm#SQLRF55422
|
918
|
+
{
|
919
|
+
read_committed: "READ COMMITTED",
|
920
|
+
serializable: "SERIALIZABLE"
|
921
|
+
}
|
922
|
+
end
|
923
|
+
|
924
|
+
def begin_isolated_db_transaction(isolation)
|
925
|
+
begin_db_transaction
|
926
|
+
execute "SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}"
|
927
|
+
end
|
928
|
+
|
778
929
|
def commit_db_transaction #:nodoc:
|
779
930
|
@connection.commit
|
780
931
|
ensure
|
@@ -838,9 +989,36 @@ module ActiveRecord
|
|
838
989
|
# Returns default sequence name for table.
|
839
990
|
# Will take all or first 26 characters of table name and append _seq suffix
|
840
991
|
def default_sequence_name(table_name, primary_key = nil)
|
841
|
-
|
842
|
-
|
843
|
-
|
992
|
+
table_name.to_s.gsub /(^|\.)([\w$-]{1,#{sequence_name_length-4}})([\w$-]*)$/, '\1\2_seq'
|
993
|
+
end
|
994
|
+
|
995
|
+
def reset_pk_sequence!(table_name, primary_key = nil, sequence_name = nil) #:nodoc:
|
996
|
+
return nil unless table_exists?(table_name)
|
997
|
+
unless primary_key and sequence_name
|
998
|
+
# *Note*: Only primary key is implemented - sequence will be nil.
|
999
|
+
primary_key, sequence_name = pk_and_sequence_for(table_name)
|
1000
|
+
# TODO This sequence_name implemantation is just enough
|
1001
|
+
# to satisty fixures. To get correct sequence_name always
|
1002
|
+
# pk_and_sequence_for method needs some work.
|
1003
|
+
begin
|
1004
|
+
sequence_name = table_name.classify.constantize.sequence_name
|
1005
|
+
rescue
|
1006
|
+
sequence_name = default_sequence_name(table_name)
|
1007
|
+
end
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
if @logger && primary_key && !sequence_name
|
1011
|
+
@logger.warn "#{table_name} has primary key #{primary_key} with no default sequence"
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
if primary_key && sequence_name
|
1015
|
+
new_start_value = select_value("
|
1016
|
+
select NVL(max(#{quote_column_name(primary_key)}),0) + 1 from #{quote_table_name(table_name)}
|
1017
|
+
", new_start_value)
|
1018
|
+
|
1019
|
+
execute ("DROP SEQUENCE #{quote_table_name(sequence_name)}")
|
1020
|
+
execute ("CREATE SEQUENCE #{quote_table_name(sequence_name)} START WITH #{new_start_value}")
|
1021
|
+
end
|
844
1022
|
end
|
845
1023
|
|
846
1024
|
# Inserts the given fixture into the table. Overridden to properly handle lobs.
|
@@ -848,9 +1026,9 @@ module ActiveRecord
|
|
848
1026
|
super
|
849
1027
|
|
850
1028
|
if ActiveRecord::Base.pluralize_table_names
|
851
|
-
klass = table_name.singularize.camelize
|
1029
|
+
klass = table_name.to_s.singularize.camelize
|
852
1030
|
else
|
853
|
-
klass = table_name.camelize
|
1031
|
+
klass = table_name.to_s.camelize
|
854
1032
|
end
|
855
1033
|
|
856
1034
|
klass = klass.constantize rescue nil
|
@@ -1093,7 +1271,7 @@ module ActiveRecord
|
|
1093
1271
|
SQL
|
1094
1272
|
|
1095
1273
|
# added deletion of ignored columns
|
1096
|
-
select_all(table_cols, name).delete_if do |row|
|
1274
|
+
select_all(table_cols, name).to_a.delete_if do |row|
|
1097
1275
|
ignored_columns && ignored_columns.include?(row['name'].downcase)
|
1098
1276
|
end.map do |row|
|
1099
1277
|
limit, scale = row['limit'], row['scale']
|
@@ -1203,23 +1381,37 @@ module ActiveRecord
|
|
1203
1381
|
# making every row the same.
|
1204
1382
|
#
|
1205
1383
|
# distinct("posts.id", "posts.created_at desc")
|
1206
|
-
def distinct(columns,
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1384
|
+
def distinct(columns, orders) #:nodoc:
|
1385
|
+
# To support Rails 4.0.0 and future releases
|
1386
|
+
# because `columns_for_distinct method introduced after Rails 4.0.0 released
|
1387
|
+
if super.respond_to?(:columns_for_distinct)
|
1388
|
+
super
|
1389
|
+
else
|
1390
|
+
order_columns = orders.map { |c|
|
1391
|
+
c = c.to_sql unless c.is_a?(String)
|
1392
|
+
# remove any ASC/DESC modifiers
|
1393
|
+
c.gsub(/\s+(ASC|DESC)\s*?/i, '')
|
1394
|
+
}.reject(&:blank?).map.with_index { |c,i|
|
1395
|
+
"FIRST_VALUE(#{c}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__"
|
1396
|
+
}
|
1397
|
+
[super].concat(order_columns).join(', ')
|
1215
1398
|
end
|
1216
|
-
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
def columns_for_distinct(columns, orders) #:nodoc:
|
1402
|
+
# construct a valid columns name for DISTINCT clause,
|
1403
|
+
# ie. one that includes the ORDER BY columns, using FIRST_VALUE such that
|
1404
|
+
# the inclusion of these columns doesn't invalidate the DISTINCT
|
1405
|
+
#
|
1406
|
+
# It does not construct DISTINCT clause. Just return column names for distinct.
|
1407
|
+
order_columns = orders.reject(&:blank?).map{ |s|
|
1408
|
+
s = s.to_sql unless s.is_a?(String)
|
1217
1409
|
# remove any ASC/DESC modifiers
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1410
|
+
s.gsub(/\s+(ASC|DESC)\s*?/i, '')
|
1411
|
+
}.reject(&:blank?).map.with_index { |column,i|
|
1412
|
+
"FIRST_VALUE(#{column}) OVER (PARTITION BY #{columns} ORDER BY #{column}) AS alias_#{i}__"
|
1413
|
+
}
|
1414
|
+
[super, *order_columns].join(', ')
|
1223
1415
|
end
|
1224
1416
|
|
1225
1417
|
def temporary_table?(table_name) #:nodoc:
|
@@ -1275,7 +1467,7 @@ module ActiveRecord
|
|
1275
1467
|
|
1276
1468
|
def select(sql, name = nil, binds = [])
|
1277
1469
|
if ActiveRecord.const_defined?(:Result)
|
1278
|
-
exec_query(sql, name, binds)
|
1470
|
+
exec_query(sql, name, binds)
|
1279
1471
|
else
|
1280
1472
|
log(sql, name) do
|
1281
1473
|
@connection.select(sql, name, false)
|
@@ -1351,19 +1543,6 @@ module ActiveRecord
|
|
1351
1543
|
end
|
1352
1544
|
end
|
1353
1545
|
|
1354
|
-
# Added LOB writing callback for sessions stored in database
|
1355
|
-
# Otherwise it is not working as Session class is defined before OracleAdapter is loaded in Rails 2.0
|
1356
|
-
if defined?(CGI::Session::ActiveRecordStore::Session)
|
1357
|
-
if !CGI::Session::ActiveRecordStore::Session.respond_to?(:after_save_callback_chain) ||
|
1358
|
-
CGI::Session::ActiveRecordStore::Session.after_save_callback_chain.detect{|cb| cb.method == :enhanced_write_lobs}.nil?
|
1359
|
-
#:stopdoc:
|
1360
|
-
class CGI::Session::ActiveRecordStore::Session
|
1361
|
-
after_save :enhanced_write_lobs
|
1362
|
-
end
|
1363
|
-
#:startdoc:
|
1364
|
-
end
|
1365
|
-
end
|
1366
|
-
|
1367
1546
|
# Implementation of standard schema definition statements and extensions for schema definition
|
1368
1547
|
require 'active_record/connection_adapters/oracle_enhanced_schema_statements'
|
1369
1548
|
require 'active_record/connection_adapters/oracle_enhanced_schema_statements_ext'
|
@@ -1374,21 +1553,12 @@ require 'active_record/connection_adapters/oracle_enhanced_schema_definitions'
|
|
1374
1553
|
# Extensions for context index definition
|
1375
1554
|
require 'active_record/connection_adapters/oracle_enhanced_context_index'
|
1376
1555
|
|
1377
|
-
# Load custom create, update, delete methods functionality
|
1378
|
-
require 'active_record/connection_adapters/oracle_enhanced_procedures'
|
1379
|
-
|
1380
1556
|
# Load additional methods for composite_primary_keys support
|
1381
1557
|
require 'active_record/connection_adapters/oracle_enhanced_cpk'
|
1382
1558
|
|
1383
1559
|
# Load patch for dirty tracking methods
|
1384
1560
|
require 'active_record/connection_adapters/oracle_enhanced_dirty'
|
1385
1561
|
|
1386
|
-
# Load rake tasks definitions
|
1387
|
-
begin
|
1388
|
-
require 'active_record/connection_adapters/oracle_enhanced_tasks'
|
1389
|
-
rescue LoadError
|
1390
|
-
end if defined?(Rails) || defined?(RAILS_ROOT)
|
1391
|
-
|
1392
1562
|
# Patches and enhancements for schema dumper
|
1393
1563
|
require 'active_record/connection_adapters/oracle_enhanced_schema_dumper'
|
1394
1564
|
|
@@ -1398,6 +1568,94 @@ require 'active_record/connection_adapters/oracle_enhanced_structure_dump'
|
|
1398
1568
|
# Add BigDecimal#to_d, Fixnum#to_d and Bignum#to_d methods if not already present
|
1399
1569
|
require 'active_record/connection_adapters/oracle_enhanced_core_ext'
|
1400
1570
|
|
1401
|
-
require 'active_record/connection_adapters/oracle_enhanced_activerecord_patches'
|
1402
|
-
|
1403
1571
|
require 'active_record/connection_adapters/oracle_enhanced_version'
|
1572
|
+
|
1573
|
+
module ActiveRecord
|
1574
|
+
autoload :OracleEnhancedProcedures, 'active_record/connection_adapters/oracle_enhanced_procedures'
|
1575
|
+
end
|
1576
|
+
|
1577
|
+
# Patches and enhancements for column dumper
|
1578
|
+
require 'active_record/connection_adapters/oracle_enhanced_column_dumper'
|
1579
|
+
|
1580
|
+
module ActiveRecord
|
1581
|
+
module ConnectionAdapters
|
1582
|
+
class OracleEnhancedAdapter < AbstractAdapter
|
1583
|
+
class SchemaCreation < AbstractAdapter::SchemaCreation
|
1584
|
+
private
|
1585
|
+
|
1586
|
+
def visit_ColumnDefinition(o)
|
1587
|
+
if o.type.to_sym == :virtual
|
1588
|
+
sql_type = type_to_sql(o.default[:type], o.limit, o.precision, o.scale) if o.default[:type]
|
1589
|
+
"#{quote_column_name(o.name)} #{sql_type} AS (#{o.default[:as]})"
|
1590
|
+
else
|
1591
|
+
super
|
1592
|
+
end
|
1593
|
+
end
|
1594
|
+
|
1595
|
+
def visit_TableDefinition(o)
|
1596
|
+
tablespace = tablespace_for(:table, o.options[:tablespace])
|
1597
|
+
create_sql = "CREATE#{' GLOBAL TEMPORARY' if o.temporary} TABLE "
|
1598
|
+
create_sql << "#{quote_table_name(o.name)} ("
|
1599
|
+
create_sql << o.columns.map { |c| accept c }.join(', ')
|
1600
|
+
create_sql << ")"
|
1601
|
+
unless o.temporary
|
1602
|
+
create_sql << " ORGANIZATION #{o.options[:organization]}" if o.options[:organization]
|
1603
|
+
create_sql << "#{tablespace}"
|
1604
|
+
end
|
1605
|
+
create_sql << " #{o.options[:options]}"
|
1606
|
+
create_sql
|
1607
|
+
end
|
1608
|
+
|
1609
|
+
def tablespace_for(obj_type, tablespace_option, table_name=nil, column_name=nil)
|
1610
|
+
tablespace_sql = ''
|
1611
|
+
if tablespace = (tablespace_option || default_tablespace_for(obj_type))
|
1612
|
+
tablespace_sql << if [:blob, :clob].include?(obj_type.to_sym)
|
1613
|
+
" LOB (#{quote_column_name(column_name)}) STORE AS #{column_name.to_s[0..10]}_#{table_name.to_s[0..14]}_ls (TABLESPACE #{tablespace})"
|
1614
|
+
else
|
1615
|
+
" TABLESPACE #{tablespace}"
|
1616
|
+
end
|
1617
|
+
end
|
1618
|
+
tablespace_sql
|
1619
|
+
end
|
1620
|
+
|
1621
|
+
def default_tablespace_for(type)
|
1622
|
+
(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[type] ||
|
1623
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[native_database_types[type][:name]]) rescue nil
|
1624
|
+
end
|
1625
|
+
|
1626
|
+
def foreign_key_definition(to_table, options = {})
|
1627
|
+
@conn.foreign_key_definition(to_table, options)
|
1628
|
+
end
|
1629
|
+
|
1630
|
+
end
|
1631
|
+
|
1632
|
+
def schema_creation
|
1633
|
+
SchemaCreation.new self
|
1634
|
+
end
|
1635
|
+
end
|
1636
|
+
|
1637
|
+
def add_column_options!(sql, options)
|
1638
|
+
type = options[:type] || ((column = options[:column]) && column.type)
|
1639
|
+
type = type && type.to_sym
|
1640
|
+
# handle case of defaults for CLOB columns, which would otherwise get "quoted" incorrectly
|
1641
|
+
if options_include_default?(options)
|
1642
|
+
if type == :text
|
1643
|
+
sql << " DEFAULT #{quote(options[:default])}"
|
1644
|
+
else
|
1645
|
+
# from abstract adapter
|
1646
|
+
sql << " DEFAULT #{quote(options[:default], options[:column])}"
|
1647
|
+
end
|
1648
|
+
end
|
1649
|
+
# must explicitly add NULL or NOT NULL to allow change_column to work on migrations
|
1650
|
+
if options[:null] == false
|
1651
|
+
sql << " NOT NULL"
|
1652
|
+
elsif options[:null] == true
|
1653
|
+
sql << " NULL" unless type == :primary_key
|
1654
|
+
end
|
1655
|
+
# add AS expression for virtual columns
|
1656
|
+
if options[:as].present?
|
1657
|
+
sql << " AS (#{options[:as]})"
|
1658
|
+
end
|
1659
|
+
end
|
1660
|
+
end
|
1661
|
+
end
|