activerecord-oracle_enhanced-adapter 1.2.2 → 1.2.3
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/.gitignore +10 -0
- data/History.txt +20 -0
- data/Manifest.txt +32 -0
- data/README.rdoc +12 -8
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +69 -13
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +7 -7
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +15 -9
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +38 -24
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +3 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +17 -11
- data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -7
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +83 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +55 -37
- data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +4 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +53 -23
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +1 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_spec.rb +3 -0
- data/spec/spec_helper.rb +12 -8
- metadata +30 -28
data/.gitignore
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
== 1.2.3 2009-12-09
|
2
|
+
|
3
|
+
* Enhancements
|
4
|
+
* support fractional seconds in TIMESTAMP values
|
5
|
+
* support for ActiveRecord 2.3.5
|
6
|
+
* use ENV['TZ'] to set database session time zone
|
7
|
+
(as a result DATE and TIMESTAMP values are retrieved with correct time zone)
|
8
|
+
* added cache_columns adapter option
|
9
|
+
* added current_user adapter method
|
10
|
+
* added set_integer_columns and set_string_columns ActiveRecord model class methods
|
11
|
+
* Bug fixes:
|
12
|
+
* do not raise exception if ENV['PATH'] is nil
|
13
|
+
* do not add change_table behavior for ActiveRecord 2.0 (to avoid exception during loading)
|
14
|
+
* move foreign key definitions after definition of all tables in schema.rb
|
15
|
+
(to avoid definition of foreign keys before all tables are created)
|
16
|
+
* changed timestamp format mask to use ':' before fractional seconds
|
17
|
+
(workaround to avoid table detection in tables_in_string method in ActiveRecord associations.rb file)
|
18
|
+
* fixed custom create/update/delete methods with ActiveRecord 2.3+ and timestamps
|
19
|
+
* do not call oracle_enhanced specific schema dump methods when using other database adapters
|
20
|
+
|
1
21
|
== 1.2.2 2009-09-28
|
2
22
|
|
3
23
|
* Enhancements
|
data/Manifest.txt
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
History.txt
|
2
|
+
License.txt
|
3
|
+
README.rdoc
|
4
|
+
lib/active_record/connection_adapters/emulation/oracle_adapter.rb
|
5
|
+
lib/active_record/connection_adapters/oracle_enhanced.rake
|
6
|
+
lib/active_record/connection_adapters/oracle_enhanced_adapter.rb
|
7
|
+
lib/active_record/connection_adapters/oracle_enhanced_connection.rb
|
8
|
+
lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb
|
9
|
+
lib/active_record/connection_adapters/oracle_enhanced_cpk.rb
|
10
|
+
lib/active_record/connection_adapters/oracle_enhanced_dirty.rb
|
11
|
+
lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb
|
12
|
+
lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb
|
13
|
+
lib/active_record/connection_adapters/oracle_enhanced_procedures.rb
|
14
|
+
lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb
|
15
|
+
lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb
|
16
|
+
lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb
|
17
|
+
lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb
|
18
|
+
lib/active_record/connection_adapters/oracle_enhanced_tasks.rb
|
19
|
+
lib/active_record/connection_adapters/oracle_enhanced_version.rb
|
20
|
+
spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb
|
21
|
+
spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb
|
22
|
+
spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb
|
23
|
+
spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb
|
24
|
+
spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb
|
25
|
+
spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb
|
26
|
+
spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb
|
27
|
+
spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb
|
28
|
+
spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb
|
29
|
+
spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb
|
30
|
+
spec/active_record/connection_adapters/oracle_enhanced_schema_spec.rb
|
31
|
+
spec/spec.opts
|
32
|
+
spec/spec_helper.rb
|
data/README.rdoc
CHANGED
@@ -1,27 +1,23 @@
|
|
1
|
-
=
|
1
|
+
= activerecord-oracle_enhanced-adapter
|
2
2
|
|
3
|
-
|
3
|
+
Oracle enhanced adapter for ActiveRecord
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
7
|
Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases
|
8
8
|
from Rails which are extracted from current real projects' monkey patches of original Oracle adapter.
|
9
9
|
|
10
|
-
See http://github.com/rsim/oracle-enhanced
|
11
|
-
|
12
|
-
See http://oracle-enhanced.rubyforge.org/rdoc for detailed API documentation.
|
10
|
+
See http://wiki.github.com/rsim/oracle-enhanced for usage information.
|
13
11
|
|
14
12
|
For questions and feature discussion please use http://groups.google.com/group/oracle-enhanced
|
15
13
|
|
16
14
|
Blog posts about oracle-enahnced can be found at http://blog.rayapps.com/category/oracle-enhanced
|
17
15
|
|
18
|
-
Bugs and enhancement requests can be reported at http://rsim.lighthouseapp.com/projects/11468-oracle-enhanced
|
19
|
-
|
20
16
|
== REQUIREMENTS:
|
21
17
|
|
22
18
|
* Works (has been tested) with ActiveRecord version 2.0, 2.1, 2.2 and 2.3 (these are the same as Rails versions)
|
23
19
|
* Can be used on the following Ruby platforms:
|
24
|
-
* MRI - requires ruby-oci8 1.x or 2.x
|
20
|
+
* MRI - requires ruby-oci8 1.x or 2.x gem to connect to Oracle (2.0.3 or later recommended)
|
25
21
|
* Ruby/YARV 1.9.1 - requires ruby-oci8 2.x library to connect to Oracle
|
26
22
|
unicode_utils gem is recommended for Unicode aware string upcase and downcase
|
27
23
|
* JRuby - uses JDBC driver ojdbc14.jar to connect to Oracle (should be in JRUBY_HOME/lib or in Java class path)
|
@@ -31,6 +27,14 @@ Bugs and enhancement requests can be reported at http://rsim.lighthouseapp.com/p
|
|
31
27
|
|
32
28
|
* [sudo] gem install activerecord-oracle_enhanced-adapter
|
33
29
|
|
30
|
+
In addition install either ruby-oci8 (for MRI/YARV) or copy Oracle JDBC driver to $JRUBY_HOME/lib (for JRuby).
|
31
|
+
|
32
|
+
== LINKS
|
33
|
+
|
34
|
+
* Source code: http://github.com/rsim/oracle-enhanced
|
35
|
+
* Bug reports / Feature requests: http://github.com/rsim/oracle-enhanced/issues
|
36
|
+
* Discuss at oracle_enhanced adapter group: http://groups.google.com/group/oracle-enhanced
|
37
|
+
|
34
38
|
== CONTRIBUTORS:
|
35
39
|
|
36
40
|
* Raimonds Simanovskis
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "activerecord-oracle_enhanced-adapter"
|
8
|
+
gem.summary = "Oracle enhanced adapter for ActiveRecord"
|
9
|
+
gem.description = <<-EOS
|
10
|
+
Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases.
|
11
|
+
This adapter is superset of original ActiveRecord Oracle adapter.
|
12
|
+
EOS
|
13
|
+
gem.email = "raimonds.simanovskis@gmail.com"
|
14
|
+
gem.homepage = "http://github.com/rsim/oracle-enhanced"
|
15
|
+
gem.authors = ["Raimonds Simanovskis"]
|
16
|
+
gem.add_dependency "activerecord", ">= 2.0.0"
|
17
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
18
|
+
gem.extra_rdoc_files = ['README.rdoc']
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'spec/rake/spectask'
|
26
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
27
|
+
spec.libs << 'lib' << 'spec'
|
28
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
29
|
+
end
|
30
|
+
|
31
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
32
|
+
spec.libs << 'lib' << 'spec'
|
33
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
34
|
+
spec.rcov = true
|
35
|
+
end
|
36
|
+
|
37
|
+
task :spec => :check_dependencies
|
38
|
+
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
require 'rake/rdoctask'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'doc'
|
46
|
+
rdoc.title = "activerecord-oracle_enhanced-adapter #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.2.3
|
@@ -78,6 +78,23 @@ module ActiveRecord
|
|
78
78
|
connection.set_type_for_columns(table_name,:boolean,*args)
|
79
79
|
end
|
80
80
|
|
81
|
+
# Specify which table columns should be typecasted to integer values.
|
82
|
+
# Might be useful to force NUMBER(1) column to be integer and not boolean, or force NUMBER column without
|
83
|
+
# scale to be retrieved as integer and not decimal. Example:
|
84
|
+
#
|
85
|
+
# set_integer_columns :version_number, :object_identifier
|
86
|
+
def self.set_integer_columns(*args)
|
87
|
+
connection.set_type_for_columns(table_name,:integer,*args)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Specify which table columns should be typecasted to string values.
|
91
|
+
# Might be useful to specify that columns should be string even if its name matches boolean column criteria.
|
92
|
+
#
|
93
|
+
# set_integer_columns :active_flag
|
94
|
+
def self.set_string_columns(*args)
|
95
|
+
connection.set_type_for_columns(table_name,:string,*args)
|
96
|
+
end
|
97
|
+
|
81
98
|
# After setting large objects to empty, select the OCI8::LOB
|
82
99
|
# and write back the data.
|
83
100
|
after_save :enhanced_write_lobs
|
@@ -170,23 +187,24 @@ module ActiveRecord
|
|
170
187
|
|
171
188
|
private
|
172
189
|
def simplified_type(field_type)
|
173
|
-
|
174
|
-
return :boolean if OracleEnhancedAdapter.emulate_booleans_from_strings &&
|
175
|
-
(forced_column_type == :boolean ||
|
176
|
-
OracleEnhancedAdapter.is_boolean_column?(name, field_type, table_name))
|
177
|
-
|
190
|
+
forced_column_type ||
|
178
191
|
case field_type
|
192
|
+
when /decimal|numeric|number/i
|
193
|
+
return :boolean if OracleEnhancedAdapter.emulate_booleans && field_type == 'NUMBER(1)'
|
194
|
+
return :integer if extract_scale(field_type) == 0
|
195
|
+
# if column name is ID or ends with _ID
|
196
|
+
return :integer if OracleEnhancedAdapter.emulate_integers_by_column_name && OracleEnhancedAdapter.is_integer_column?(name, table_name)
|
197
|
+
:decimal
|
198
|
+
when /char/i
|
199
|
+
return :boolean if OracleEnhancedAdapter.emulate_booleans_from_strings &&
|
200
|
+
OracleEnhancedAdapter.is_boolean_column?(name, field_type, table_name)
|
201
|
+
:string
|
179
202
|
when /date/i
|
180
203
|
forced_column_type ||
|
181
204
|
(:date if OracleEnhancedAdapter.emulate_dates_by_column_name && OracleEnhancedAdapter.is_date_column?(name, table_name)) ||
|
182
205
|
:datetime
|
183
206
|
when /timestamp/i then :timestamp
|
184
207
|
when /time/i then :datetime
|
185
|
-
when /decimal|numeric|number/i
|
186
|
-
return :integer if extract_scale(field_type) == 0
|
187
|
-
# if column name is ID or ends with _ID
|
188
|
-
return :integer if OracleEnhancedAdapter.emulate_integers_by_column_name && OracleEnhancedAdapter.is_integer_column?(name, table_name)
|
189
|
-
:decimal
|
190
208
|
else super
|
191
209
|
end
|
192
210
|
end
|
@@ -263,6 +281,8 @@ module ActiveRecord
|
|
263
281
|
# * <tt>:cursor_sharing</tt> - cursor sharing mode to minimize amount of unique statements, defaults to "force"
|
264
282
|
# * <tt>:nls_length_semantics</tt> - semantics of size of VARCHAR2 and CHAR columns, defaults to "CHAR"
|
265
283
|
# (meaning that size specifies number of characters and not bytes)
|
284
|
+
# * <tt>:time_zone</tt> - database session time zone
|
285
|
+
# (it is recommended to set it using ENV['TZ'] which will be then also used for database session time zone)
|
266
286
|
class OracleEnhancedAdapter < AbstractAdapter
|
267
287
|
|
268
288
|
##
|
@@ -363,12 +383,16 @@ module ActiveRecord
|
|
363
383
|
bool ? "Y" : "N"
|
364
384
|
end
|
365
385
|
|
386
|
+
##
|
387
|
+
# :singleton-method:
|
366
388
|
# Specify non-default date format that should be used when assigning string values to :date columns, e.g.:
|
367
389
|
#
|
368
390
|
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = “%d.%m.%Y”
|
369
391
|
cattr_accessor :string_to_date_format
|
370
392
|
self.string_to_date_format = nil
|
371
393
|
|
394
|
+
##
|
395
|
+
# :singleton-method:
|
372
396
|
# Specify non-default time format that should be used when assigning string values to :datetime columns, e.g.:
|
373
397
|
#
|
374
398
|
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = “%d.%m.%Y %H:%M:%S”
|
@@ -490,8 +514,8 @@ module ActiveRecord
|
|
490
514
|
|
491
515
|
def quote_timestamp_with_to_timestamp(value) #:nodoc:
|
492
516
|
# add up to 9 digits of fractional seconds to inserted time
|
493
|
-
value = "#{quoted_date(value)}
|
494
|
-
"TO_TIMESTAMP('#{value}','YYYY-MM-DD HH24:MI:SS
|
517
|
+
value = "#{quoted_date(value)}:#{("%.6f"%value.to_f).split('.')[1]}" if value.acts_like?(:time)
|
518
|
+
"TO_TIMESTAMP('#{value}','YYYY-MM-DD HH24:MI:SS:FF6')"
|
495
519
|
end
|
496
520
|
|
497
521
|
# CONNECTION MANAGEMENT ====================================
|
@@ -689,10 +713,16 @@ module ActiveRecord
|
|
689
713
|
#
|
690
714
|
# see: abstract/schema_statements.rb
|
691
715
|
|
692
|
-
|
716
|
+
# current database name
|
717
|
+
def current_database
|
693
718
|
select_one("select sys_context('userenv','db_name') db from dual")["db"]
|
694
719
|
end
|
695
720
|
|
721
|
+
# current database session user
|
722
|
+
def current_user
|
723
|
+
select_one("select sys_context('userenv','session_user') u from dual")['u']
|
724
|
+
end
|
725
|
+
|
696
726
|
def tables(name = nil) #:nodoc:
|
697
727
|
# changed select from user_tables to all_tables - much faster in large data dictionaries
|
698
728
|
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']}
|
@@ -793,7 +823,27 @@ module ActiveRecord
|
|
793
823
|
select_value(pkt_sql) ? true : false
|
794
824
|
end
|
795
825
|
|
826
|
+
##
|
827
|
+
# :singleton-method:
|
828
|
+
# Cache column description between requests.
|
829
|
+
# Could be used in development environment to avoid selecting table columns from data dictionary tables for each request.
|
830
|
+
# This can speed up request processing in development mode if development database is not on local computer.
|
831
|
+
#
|
832
|
+
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = true
|
833
|
+
cattr_accessor :cache_columns
|
834
|
+
self.cache_columns = false
|
835
|
+
|
796
836
|
def columns(table_name, name = nil) #:nodoc:
|
837
|
+
# Don't double cache if config.cache_classes is turned on
|
838
|
+
if @@cache_columns && !(defined?(Rails) && Rails.configuration.cache_classes)
|
839
|
+
@@columns_cache ||= {}
|
840
|
+
@@columns_cache[table_name] ||= columns_without_cache(table_name, name)
|
841
|
+
else
|
842
|
+
columns_without_cache(table_name, name)
|
843
|
+
end
|
844
|
+
end
|
845
|
+
|
846
|
+
def columns_without_cache(table_name, name = nil) #:nodoc:
|
797
847
|
# get ignored_columns by original table name
|
798
848
|
ignored_columns = ignored_table_columns(table_name)
|
799
849
|
|
@@ -844,6 +894,11 @@ module ActiveRecord
|
|
844
894
|
end
|
845
895
|
end
|
846
896
|
|
897
|
+
# used just in tests to clear column cache
|
898
|
+
def clear_columns_cache #:nodoc:
|
899
|
+
@@columns_cache = nil
|
900
|
+
end
|
901
|
+
|
847
902
|
##
|
848
903
|
# :singleton-method:
|
849
904
|
# Specify default sequence start with value (by default 10000 if not explicitly set), e.g.:
|
@@ -1379,3 +1434,4 @@ require 'active_record/connection_adapters/oracle_enhanced_schema_definitions'
|
|
1379
1434
|
# Add BigDecimal#to_d, Fixnum#to_d and Bignum#to_d methods if not already present
|
1380
1435
|
require 'active_record/connection_adapters/oracle_enhanced_core_ext'
|
1381
1436
|
|
1437
|
+
require 'active_record/connection_adapters/oracle_enhanced_version'
|
@@ -7,11 +7,9 @@ begin
|
|
7
7
|
ojdbc_jar = "ojdbc14.jar"
|
8
8
|
|
9
9
|
unless ENV_JAVA['java.class.path'] =~ Regexp.new(ojdbc_jar)
|
10
|
-
#
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
if ojdbc_jar_path = ENV["PATH"].split(/[:;]/).concat($LOAD_PATH).find{|d| File.exists?(File.join(d,ojdbc_jar))}
|
10
|
+
# On Unix environment variable should be PATH, on Windows it is sometimes Path
|
11
|
+
env_path = ENV["PATH"] || ENV["Path"] || ''
|
12
|
+
if ojdbc_jar_path = env_path.split(/[:;]/).concat($LOAD_PATH).find{|d| File.exists?(File.join(d,ojdbc_jar))}
|
15
13
|
require File.join(ojdbc_jar_path,ojdbc_jar)
|
16
14
|
end
|
17
15
|
end
|
@@ -71,6 +69,8 @@ module ActiveRecord
|
|
71
69
|
cursor_sharing = config[:cursor_sharing] || 'force'
|
72
70
|
# by default VARCHAR2 column size will be interpreted as max number of characters (and not bytes)
|
73
71
|
nls_length_semantics = config[:nls_length_semantics] || 'CHAR'
|
72
|
+
# get session time_zone from configuration or from TZ environment variable
|
73
|
+
time_zone = config[:time_zone] || ENV['TZ'] || java.util.TimeZone.default.getID
|
74
74
|
|
75
75
|
properties = java.util.Properties.new
|
76
76
|
properties.put("user", username)
|
@@ -80,13 +80,13 @@ module ActiveRecord
|
|
80
80
|
|
81
81
|
@raw_connection = java.sql.DriverManager.getConnection(url, properties)
|
82
82
|
exec %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'}
|
83
|
-
exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'}
|
83
|
+
exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS:FF6'}
|
84
84
|
exec "alter session set cursor_sharing = #{cursor_sharing}"
|
85
85
|
exec "alter session set nls_length_semantics = '#{nls_length_semantics}'"
|
86
86
|
self.autocommit = true
|
87
87
|
|
88
88
|
# Set session time zone to current time zone
|
89
|
-
@raw_connection.setSessionTimeZone(
|
89
|
+
@raw_connection.setSessionTimeZone(time_zone)
|
90
90
|
|
91
91
|
# Set default number of rows to prefetch
|
92
92
|
# @raw_connection.setDefaultRowPrefetch(prefetch_rows) if prefetch_rows
|
@@ -4,10 +4,11 @@ begin
|
|
4
4
|
require 'oci8' unless self.class.const_defined? :OCI8
|
5
5
|
|
6
6
|
# added mapping for TIMESTAMP / WITH TIME ZONE / LOCAL TIME ZONE types
|
7
|
-
#
|
8
|
-
|
9
|
-
OCI8::BindType::Mapping[OCI8::
|
10
|
-
OCI8::BindType::Mapping[OCI8::
|
7
|
+
# latest version of Ruby-OCI8 supports fractional seconds for timestamps
|
8
|
+
# therefore default binding to Time class should be used
|
9
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP] = OCI8::BindType::OraDate
|
10
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_TZ] = OCI8::BindType::OraDate
|
11
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_LTZ] = OCI8::BindType::OraDate
|
11
12
|
rescue LoadError
|
12
13
|
# OCI8 driver is unavailable.
|
13
14
|
error_message = "ERROR: ActiveRecord oracle_enhanced adapter could not load ruby-oci8 library. "+
|
@@ -192,15 +193,17 @@ module ActiveRecord
|
|
192
193
|
end
|
193
194
|
|
194
195
|
def create_time_with_default_timezone(value)
|
195
|
-
year, month, day, hour, min, sec = case value
|
196
|
+
year, month, day, hour, min, sec, usec = case value
|
197
|
+
when Time
|
198
|
+
[value.year, value.month, value.day, value.hour, value.min, value.sec, value.usec]
|
196
199
|
when OraDate
|
197
|
-
[value.year, value.month, value.day, value.hour, value.minute, value.second]
|
200
|
+
[value.year, value.month, value.day, value.hour, value.minute, value.second, 0]
|
198
201
|
else
|
199
|
-
[value.year, value.month, value.day, value.hour, value.min, value.sec]
|
202
|
+
[value.year, value.month, value.day, value.hour, value.min, value.sec, 0]
|
200
203
|
end
|
201
204
|
# code from Time.time_with_datetime_fallback
|
202
205
|
begin
|
203
|
-
Time.send(Base.default_timezone, year, month, day, hour, min, sec)
|
206
|
+
Time.send(Base.default_timezone, year, month, day, hour, min, sec, usec)
|
204
207
|
rescue
|
205
208
|
offset = Base.default_timezone.to_sym == :local ? ::DateTime.local_offset : 0
|
206
209
|
::DateTime.civil(year, month, day, hour, min, sec, offset)
|
@@ -219,15 +222,18 @@ module ActiveRecord
|
|
219
222
|
cursor_sharing = config[:cursor_sharing] || 'force'
|
220
223
|
# by default VARCHAR2 column size will be interpreted as max number of characters (and not bytes)
|
221
224
|
nls_length_semantics = config[:nls_length_semantics] || 'CHAR'
|
225
|
+
# get session time_zone from configuration or from TZ environment variable
|
226
|
+
time_zone = config[:time_zone] || ENV['TZ']
|
222
227
|
|
223
228
|
conn = OCI8.new username, password, database, privilege
|
224
229
|
conn.exec %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'}
|
225
|
-
conn.exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'} rescue nil
|
230
|
+
conn.exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS:FF6'} rescue nil
|
226
231
|
conn.autocommit = true
|
227
232
|
conn.non_blocking = true if async
|
228
233
|
conn.prefetch_rows = prefetch_rows
|
229
234
|
conn.exec "alter session set cursor_sharing = #{cursor_sharing}" rescue nil
|
230
235
|
conn.exec "alter session set nls_length_semantics = '#{nls_length_semantics}'"
|
236
|
+
conn.exec "alter session set time_zone = '#{time_zone}'" unless time_zone.blank?
|
231
237
|
conn
|
232
238
|
end
|
233
239
|
end
|
@@ -5,7 +5,7 @@ ActiveRecord::Base.class_eval do
|
|
5
5
|
end
|
6
6
|
|
7
7
|
require 'ruby_plsql'
|
8
|
-
require '
|
8
|
+
require 'active_support'
|
9
9
|
|
10
10
|
module ActiveRecord #:nodoc:
|
11
11
|
module ConnectionAdapters #:nodoc:
|
@@ -53,6 +53,36 @@ module ActiveRecord #:nodoc:
|
|
53
53
|
self.custom_delete_method = block
|
54
54
|
end
|
55
55
|
|
56
|
+
def create_method_name_before_custom_methods
|
57
|
+
if private_method_defined?(:create_without_timestamps) && defined?(ActiveRecord::VERSION) && ActiveRecord::VERSION::STRING.to_f >= 2.3
|
58
|
+
:create_without_timestamps
|
59
|
+
elsif private_method_defined?(:create_without_callbacks)
|
60
|
+
:create_without_callbacks
|
61
|
+
else
|
62
|
+
:create
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def update_method_name_before_custom_methods
|
67
|
+
if private_method_defined?(:update_without_dirty)
|
68
|
+
:update_without_dirty
|
69
|
+
elsif private_method_defined?(:update_without_timestamps) && defined?(ActiveRecord::VERSION) && ActiveRecord::VERSION::STRING.to_f >= 2.3
|
70
|
+
:update_without_timestamps
|
71
|
+
elsif private_method_defined?(:update_without_callbacks)
|
72
|
+
:update_without_callbacks
|
73
|
+
else
|
74
|
+
:update
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def destroy_method_name_before_custom_methods
|
79
|
+
if public_method_defined?(:destroy_without_callbacks)
|
80
|
+
:destroy_without_callbacks
|
81
|
+
else
|
82
|
+
:destroy
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
56
86
|
private
|
57
87
|
def include_with_custom_methods
|
58
88
|
unless included_modules.include? InstanceMethods
|
@@ -64,30 +94,13 @@ module ActiveRecord #:nodoc:
|
|
64
94
|
module InstanceMethods #:nodoc:
|
65
95
|
def self.included(base)
|
66
96
|
base.instance_eval do
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
# insert after dirty checking in Rails 2.1
|
74
|
-
# in Ruby 1.9 methods names are returned as symbols
|
75
|
-
if private_instance_methods.include?('update_without_dirty') || private_instance_methods.include?(:update_without_dirty)
|
76
|
-
alias_method :update_without_custom_method, :update_without_dirty
|
77
|
-
alias_method :update_without_dirty, :update_with_custom_method
|
78
|
-
elsif private_instance_methods.include?('update_without_callbacks') || private_instance_methods.include?(:update_without_callbacks)
|
79
|
-
alias_method :update_without_custom_method, :update_without_callbacks
|
80
|
-
alias_method :update_without_callbacks, :update_with_custom_method
|
81
|
-
else
|
82
|
-
alias_method_chain :update, :custom_method
|
83
|
-
end
|
97
|
+
alias_method :create_without_custom_method, create_method_name_before_custom_methods
|
98
|
+
alias_method create_method_name_before_custom_methods, :create_with_custom_method
|
99
|
+
alias_method :update_without_custom_method, update_method_name_before_custom_methods
|
100
|
+
alias_method update_method_name_before_custom_methods, :update_with_custom_method
|
101
|
+
alias_method :destroy_without_custom_method, destroy_method_name_before_custom_methods
|
102
|
+
alias_method destroy_method_name_before_custom_methods, :destroy_with_custom_method
|
84
103
|
private :create, :update
|
85
|
-
if public_instance_methods.include?('destroy_without_callbacks') || public_instance_methods.include?(:destroy_without_callbacks)
|
86
|
-
alias_method :destroy_without_custom_method, :destroy_without_callbacks
|
87
|
-
alias_method :destroy_without_callbacks, :destroy_with_custom_method
|
88
|
-
else
|
89
|
-
alias_method_chain :destroy, :custom_method
|
90
|
-
end
|
91
104
|
public :destroy
|
92
105
|
end
|
93
106
|
end
|
@@ -130,6 +143,7 @@ module ActiveRecord #:nodoc:
|
|
130
143
|
end
|
131
144
|
end
|
132
145
|
|
146
|
+
@destroyed = true
|
133
147
|
freeze
|
134
148
|
end
|
135
149
|
|
@@ -12,9 +12,10 @@ module ActiveRecord
|
|
12
12
|
include OracleEnhancedTableDefinition
|
13
13
|
end
|
14
14
|
|
15
|
+
# Available starting from ActiveRecord 2.1
|
15
16
|
base::Table.class_eval do
|
16
17
|
include OracleEnhancedTable
|
17
|
-
end
|
18
|
+
end if defined?(base::Table)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
@@ -80,7 +81,7 @@ module ActiveRecord
|
|
80
81
|
|
81
82
|
def to_sql_with_foreign_keys #:nodoc:
|
82
83
|
sql = to_sql_without_foreign_keys
|
83
|
-
sql << ', ' << (foreign_keys * ', ')
|
84
|
+
sql << ', ' << (foreign_keys * ', ') unless foreign_keys.blank?
|
84
85
|
sql
|
85
86
|
end
|
86
87
|
|
@@ -13,7 +13,8 @@ module ActiveRecord #:nodoc:
|
|
13
13
|
private
|
14
14
|
|
15
15
|
def tables_with_oracle_enhanced(stream)
|
16
|
-
@connection.tables.sort
|
16
|
+
sorted_tables = @connection.tables.sort
|
17
|
+
sorted_tables.each do |tbl|
|
17
18
|
# add table prefix or suffix for schema_migrations
|
18
19
|
next if [ActiveRecord::Migrator.proper_table_name('schema_migrations'), ignore_tables].flatten.any? do |ignored|
|
19
20
|
case ignored
|
@@ -28,9 +29,12 @@ module ActiveRecord #:nodoc:
|
|
28
29
|
table(tbl, stream)
|
29
30
|
# add primary key trigger if table has it
|
30
31
|
primary_key_trigger(tbl, stream)
|
32
|
+
end
|
33
|
+
sorted_tables.each do |tbl|
|
31
34
|
# add foreign keys if table has them
|
32
35
|
foreign_keys(tbl, stream)
|
33
36
|
end
|
37
|
+
# add synonyms in local schema
|
34
38
|
synonyms(stream)
|
35
39
|
end
|
36
40
|
|
@@ -44,7 +48,7 @@ module ActiveRecord #:nodoc:
|
|
44
48
|
end
|
45
49
|
|
46
50
|
def foreign_keys(table_name, stream)
|
47
|
-
if (foreign_keys = @connection.foreign_keys(table_name)).any?
|
51
|
+
if @connection.respond_to?(:foreign_keys) && (foreign_keys = @connection.foreign_keys(table_name)).any?
|
48
52
|
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
49
53
|
statement_parts = [ ('add_foreign_key ' + foreign_key.from_table.inspect) ]
|
50
54
|
statement_parts << foreign_key.to_table.inspect
|
@@ -56,7 +60,7 @@ module ActiveRecord #:nodoc:
|
|
56
60
|
if foreign_key.options[:primary_key] != 'id'
|
57
61
|
statement_parts << (':primary_key => ' + foreign_key.options[:primary_key].inspect)
|
58
62
|
end
|
59
|
-
|
63
|
+
unless foreign_key.options[:dependent].blank?
|
60
64
|
statement_parts << (':dependent => ' + foreign_key.options[:dependent].inspect)
|
61
65
|
end
|
62
66
|
|
@@ -69,15 +73,17 @@ module ActiveRecord #:nodoc:
|
|
69
73
|
end
|
70
74
|
|
71
75
|
def synonyms(stream)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
if @connection.respond_to?(:synonyms)
|
77
|
+
syns = @connection.synonyms
|
78
|
+
syns.each do |syn|
|
79
|
+
table_name = syn.table_name
|
80
|
+
table_name = "#{syn.table_owner}.#{table_name}" if syn.table_owner
|
81
|
+
table_name = "#{table_name}@#{syn.db_link}" if syn.db_link
|
82
|
+
stream.print " add_synonym #{syn.name.inspect}, #{table_name.inspect}, :force => true"
|
83
|
+
stream.puts
|
84
|
+
end
|
85
|
+
stream.puts unless syns.empty?
|
79
86
|
end
|
80
|
-
stream.puts unless syns.empty?
|
81
87
|
end
|
82
88
|
|
83
89
|
def indexes_with_oracle_enhanced(table, stream)
|
@@ -34,6 +34,8 @@ describe "OracleEnhancedAdapter establish connection" do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
describe "OracleEnhancedAdapter" do
|
37
|
+
include LoggerSpecHelper
|
38
|
+
|
37
39
|
before(:all) do
|
38
40
|
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
39
41
|
@conn = ActiveRecord::Base.connection
|
@@ -173,6 +175,77 @@ describe "OracleEnhancedAdapter" do
|
|
173
175
|
|
174
176
|
end
|
175
177
|
|
178
|
+
describe "cache table columns" do
|
179
|
+
before(:all) do
|
180
|
+
@conn.execute "DROP TABLE test_employees" rescue nil
|
181
|
+
@conn.execute <<-SQL
|
182
|
+
CREATE TABLE test_employees (
|
183
|
+
id NUMBER,
|
184
|
+
first_name VARCHAR2(20),
|
185
|
+
last_name VARCHAR2(25),
|
186
|
+
hire_date DATE
|
187
|
+
)
|
188
|
+
SQL
|
189
|
+
@column_names = ['id', 'first_name', 'last_name', 'hire_date']
|
190
|
+
class ::TestEmployee < ActiveRecord::Base
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
after(:all) do
|
195
|
+
Object.send(:remove_const, "TestEmployee")
|
196
|
+
@conn.execute "DROP TABLE test_employees"
|
197
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = nil
|
198
|
+
end
|
199
|
+
|
200
|
+
before(:each) do
|
201
|
+
@buffer = StringIO.new
|
202
|
+
log_to @buffer
|
203
|
+
@conn = ActiveRecord::Base.connection
|
204
|
+
@conn.clear_columns_cache
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "without column caching" do
|
208
|
+
|
209
|
+
before(:each) do
|
210
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = false
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should get columns from database at first time" do
|
214
|
+
TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
|
215
|
+
@buffer.string.should =~ /select .* from all_tab_columns/im
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should get columns from database at second time" do
|
219
|
+
TestEmployee.connection.columns('test_employees')
|
220
|
+
@buffer.truncate(0)
|
221
|
+
TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
|
222
|
+
@buffer.string.should =~ /select .* from all_tab_columns/im
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
describe "with column caching" do
|
228
|
+
|
229
|
+
before(:each) do
|
230
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.cache_columns = true
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should get columns from database at first time" do
|
234
|
+
TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
|
235
|
+
@buffer.string.should =~ /select .* from all_tab_columns/im
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should get columns from cache at second time" do
|
239
|
+
TestEmployee.connection.columns('test_employees')
|
240
|
+
@buffer.truncate(0)
|
241
|
+
TestEmployee.connection.columns('test_employees').map(&:name).should == @column_names
|
242
|
+
@buffer.string.should be_blank
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
|
176
249
|
describe "without composite_primary_keys" do
|
177
250
|
|
178
251
|
before(:all) do
|
@@ -362,4 +435,14 @@ describe "OracleEnhancedAdapter" do
|
|
362
435
|
|
363
436
|
end
|
364
437
|
|
438
|
+
describe "session information" do
|
439
|
+
it "should get current database name" do
|
440
|
+
@conn.current_database.should == CONNECTION_PARAMS[:database]
|
441
|
+
end
|
442
|
+
|
443
|
+
it "should get current database session user" do
|
444
|
+
@conn.current_user.should == CONNECTION_PARAMS[:username].upcase
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
365
448
|
end
|
@@ -105,7 +105,7 @@ describe "OracleEnhancedAdapter date type detection based on column names" do
|
|
105
105
|
after(:each) do
|
106
106
|
# @employee.destroy if @employee
|
107
107
|
Object.send(:remove_const, "TestEmployee")
|
108
|
-
|
108
|
+
@conn.clear_types_for_columns
|
109
109
|
end
|
110
110
|
|
111
111
|
it "should return Time value from DATE column if emulate_dates_by_column_name is false" do
|
@@ -202,6 +202,7 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
202
202
|
salary NUMBER,
|
203
203
|
commission_pct NUMBER(2,2),
|
204
204
|
manager_id NUMBER(6),
|
205
|
+
is_manager NUMBER(1),
|
205
206
|
department_id NUMBER(4,0),
|
206
207
|
created_at DATE
|
207
208
|
)
|
@@ -262,6 +263,8 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
262
263
|
|
263
264
|
after(:each) do
|
264
265
|
Object.send(:remove_const, "Test2Employee")
|
266
|
+
@conn.clear_types_for_columns
|
267
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = true
|
265
268
|
end
|
266
269
|
|
267
270
|
def create_employee2
|
@@ -269,6 +272,7 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
269
272
|
:first_name => "First",
|
270
273
|
:last_name => "Last",
|
271
274
|
:job_id => 1,
|
275
|
+
:is_manager => 1,
|
272
276
|
:salary => 1000
|
273
277
|
)
|
274
278
|
@employee2.reload
|
@@ -292,6 +296,32 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
292
296
|
@employee2.salary.class.should == BigDecimal
|
293
297
|
end
|
294
298
|
|
299
|
+
it "should return Fixnum value from NUMBER column if column specified in set_integer_columns" do
|
300
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
|
301
|
+
Test2Employee.set_integer_columns :job_id
|
302
|
+
create_employee2
|
303
|
+
@employee2.job_id.class.should == Fixnum
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should return Boolean value from NUMBER(1) column if emulate booleans is used" do
|
307
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = true
|
308
|
+
create_employee2
|
309
|
+
@employee2.is_manager.class.should == TrueClass
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should return Fixnum value from NUMBER(1) column if emulate booleans is not used" do
|
313
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = false
|
314
|
+
create_employee2
|
315
|
+
@employee2.is_manager.class.should == Fixnum
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should return Fixnum value from NUMBER(1) column if column specified in set_integer_columns" do
|
319
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans = true
|
320
|
+
Test2Employee.set_integer_columns :is_manager
|
321
|
+
create_employee2
|
322
|
+
@employee2.is_manager.class.should == Fixnum
|
323
|
+
end
|
324
|
+
|
295
325
|
end
|
296
326
|
|
297
327
|
end
|
@@ -330,6 +360,7 @@ describe "OracleEnhancedAdapter boolean type detection based on string column ty
|
|
330
360
|
after(:all) do
|
331
361
|
@conn.execute "DROP TABLE test3_employees"
|
332
362
|
@conn.execute "DROP SEQUENCE test3_employees_seq"
|
363
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
|
333
364
|
end
|
334
365
|
|
335
366
|
it "should set CHAR/VARCHAR2 column type as string if emulate_booleans_from_strings is false" do
|
@@ -384,7 +415,7 @@ describe "OracleEnhancedAdapter boolean type detection based on string column ty
|
|
384
415
|
:boolean, nil, nil, nil).should == "VARCHAR2(1)"
|
385
416
|
end
|
386
417
|
|
387
|
-
it "should translate boolean type to NUMBER(1) if emulate_booleans_from_strings is
|
418
|
+
it "should translate boolean type to NUMBER(1) if emulate_booleans_from_strings is false" do
|
388
419
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = false
|
389
420
|
ActiveRecord::Base.connection.type_to_sql(
|
390
421
|
:boolean, nil, nil, nil).should == "NUMBER(1)"
|
@@ -406,6 +437,7 @@ describe "OracleEnhancedAdapter boolean type detection based on string column ty
|
|
406
437
|
|
407
438
|
after(:each) do
|
408
439
|
Object.send(:remove_const, "Test3Employee")
|
440
|
+
@conn.clear_types_for_columns
|
409
441
|
end
|
410
442
|
|
411
443
|
def create_employee3(params={})
|
@@ -451,9 +483,7 @@ describe "OracleEnhancedAdapter boolean type detection based on string column ty
|
|
451
483
|
|
452
484
|
it "should return boolean value from VARCHAR2 boolean column if column specified in set_boolean_columns" do
|
453
485
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
|
454
|
-
|
455
|
-
set_boolean_columns :test_boolean
|
456
|
-
end
|
486
|
+
Test3Employee.set_boolean_columns :test_boolean
|
457
487
|
create_employee3(:test_boolean => true)
|
458
488
|
@employee3.test_boolean.class.should == TrueClass
|
459
489
|
@employee3.test_boolean_before_type_cast.should == "Y"
|
@@ -467,7 +497,14 @@ describe "OracleEnhancedAdapter boolean type detection based on string column ty
|
|
467
497
|
@employee3.test_boolean.class.should == NilClass
|
468
498
|
@employee3.test_boolean_before_type_cast.should == nil
|
469
499
|
end
|
470
|
-
|
500
|
+
|
501
|
+
it "should return string value from VARCHAR2 column with boolean column name but is specified in set_string_columns" do
|
502
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_booleans_from_strings = true
|
503
|
+
Test3Employee.set_string_columns :active_flag
|
504
|
+
create_employee3
|
505
|
+
@employee3.active_flag.class.should == String
|
506
|
+
end
|
507
|
+
|
471
508
|
end
|
472
509
|
|
473
510
|
end
|
@@ -523,7 +560,6 @@ describe "OracleEnhancedAdapter timestamp with timezone support" do
|
|
523
560
|
end
|
524
561
|
|
525
562
|
it "should return Time value from TIMESTAMP columns" do
|
526
|
-
# currently fractional seconds are not retrieved from database
|
527
563
|
@now = Time.local(2008,5,26,23,11,11,0)
|
528
564
|
@employee = TestEmployee.create(
|
529
565
|
:created_at => @now,
|
@@ -537,35 +573,17 @@ describe "OracleEnhancedAdapter timestamp with timezone support" do
|
|
537
573
|
end
|
538
574
|
end
|
539
575
|
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
@now
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
@employee.
|
550
|
-
|
551
|
-
@employee.send(c).class.should == Time
|
552
|
-
@employee.send(c).to_f.should == @now.to_f
|
553
|
-
end
|
554
|
-
end
|
555
|
-
else
|
556
|
-
it "should return Time value without fractional seconds from TIMESTAMP columns" do
|
557
|
-
# currently fractional seconds are not retrieved from database
|
558
|
-
@now = Time.local(2008,5,26,23,11,11,10)
|
559
|
-
@employee = TestEmployee.create(
|
560
|
-
:created_at => @now,
|
561
|
-
:created_at_tz => @now,
|
562
|
-
:created_at_ltz => @now
|
563
|
-
)
|
564
|
-
@employee.reload
|
565
|
-
[:created_at, :created_at_tz, :created_at_ltz].each do |c|
|
566
|
-
@employee.send(c).class.should == Time
|
567
|
-
@employee.send(c).to_f.should == @now.to_f.to_i.to_f # remove fractional seconds
|
568
|
-
end
|
576
|
+
it "should return Time value with fractional seconds from TIMESTAMP columns" do
|
577
|
+
@now = Time.local(2008,5,26,23,11,11,10)
|
578
|
+
@employee = TestEmployee.create(
|
579
|
+
:created_at => @now,
|
580
|
+
:created_at_tz => @now,
|
581
|
+
:created_at_ltz => @now
|
582
|
+
)
|
583
|
+
@employee.reload
|
584
|
+
[:created_at, :created_at_tz, :created_at_ltz].each do |c|
|
585
|
+
@employee.send(c).class.should == Time
|
586
|
+
@employee.send(c).to_f.should == @now.to_f
|
569
587
|
end
|
570
588
|
end
|
571
589
|
|
@@ -674,7 +692,7 @@ describe "OracleEnhancedAdapter date and timestamp with different NLS date forma
|
|
674
692
|
it "should quote Time values with TO_TIMESTAMP" do
|
675
693
|
@ts = @now + 0.1
|
676
694
|
@conn.quote(@ts).should == "TO_TIMESTAMP('#{@ts.year}-#{"%02d" % @ts.month}-#{"%02d" % @ts.day} "+
|
677
|
-
"#{"%02d" % @ts.hour}:#{"%02d" % @ts.min}:#{"%02d" % @ts.sec}
|
695
|
+
"#{"%02d" % @ts.hour}:#{"%02d" % @ts.min}:#{"%02d" % @ts.sec}:100000','YYYY-MM-DD HH24:MI:SS:FF6')"
|
678
696
|
end
|
679
697
|
|
680
698
|
end
|
@@ -26,6 +26,10 @@ describe "OracleEnhancedAdapter logging dbms_output from plsql" do
|
|
26
26
|
SQL
|
27
27
|
end
|
28
28
|
|
29
|
+
after(:all) do
|
30
|
+
ActiveRecord::Base.connection.execute "DROP FUNCTION MORE_THAN_FIVE_CHARACTERS_LONG"
|
31
|
+
end
|
32
|
+
|
29
33
|
before(:each) do
|
30
34
|
@buffer = StringIO.new
|
31
35
|
log_to @buffer
|
@@ -6,7 +6,7 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
6
6
|
before(:all) do
|
7
7
|
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
8
8
|
@conn = ActiveRecord::Base.connection
|
9
|
-
plsql.
|
9
|
+
plsql.activerecord_class = ActiveRecord::Base
|
10
10
|
@conn.execute("DROP TABLE test_employees") rescue nil
|
11
11
|
@conn.execute <<-SQL
|
12
12
|
CREATE TABLE test_employees (
|
@@ -18,7 +18,9 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
18
18
|
description CLOB,
|
19
19
|
version NUMBER(15,0),
|
20
20
|
create_time DATE,
|
21
|
-
update_time DATE
|
21
|
+
update_time DATE,
|
22
|
+
created_at DATE,
|
23
|
+
updated_at DATE
|
22
24
|
)
|
23
25
|
SQL
|
24
26
|
@conn.execute("DROP SEQUENCE test_employees_s") rescue nil
|
@@ -168,10 +170,9 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
168
170
|
TestEmployee.class_eval { def after_create() raise "Make the transaction rollback" end }
|
169
171
|
begin
|
170
172
|
employees_count = TestEmployee.count
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
e.message.should == "Make the transaction rollback"
|
173
|
+
lambda {
|
174
|
+
@employee.save
|
175
|
+
}.should raise_error("Make the transaction rollback")
|
175
176
|
@employee.id.should == nil
|
176
177
|
TestEmployee.count.should == employees_count
|
177
178
|
ensure
|
@@ -205,10 +206,9 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
205
206
|
empl_id = @employee.id
|
206
207
|
@employee.reload
|
207
208
|
@employee.first_name = "Second"
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
e.message.should == "Make the transaction rollback"
|
209
|
+
lambda {
|
210
|
+
@employee.save
|
211
|
+
}.should raise_error("Make the transaction rollback")
|
212
212
|
@employee.reload
|
213
213
|
@employee.first_name.should == "First"
|
214
214
|
ensure
|
@@ -257,20 +257,31 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
257
257
|
TestEmployee.find_by_employee_id(empl_id).should be_nil
|
258
258
|
end
|
259
259
|
|
260
|
-
it "should
|
261
|
-
|
260
|
+
it "should delete record and set destroyed flag" do
|
261
|
+
return pending("Not in this ActiveRecord version (requires >= 2.3.5)") unless TestEmployee.method_defined?(:destroyed?)
|
262
262
|
@employee = TestEmployee.create(
|
263
263
|
:first_name => "First",
|
264
264
|
:last_name => "Last",
|
265
265
|
:hire_date => @today
|
266
266
|
)
|
267
267
|
@employee.reload
|
268
|
-
|
268
|
+
@employee.destroy
|
269
|
+
@employee.should be_destroyed
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should rollback record when exception is raised in after_desotry callback" do
|
273
|
+
TestEmployee.class_eval { def after_destroy() raise "Make the transaction rollback" end }
|
269
274
|
begin
|
270
|
-
@employee.
|
271
|
-
|
272
|
-
|
273
|
-
|
275
|
+
@employee = TestEmployee.create(
|
276
|
+
:first_name => "First",
|
277
|
+
:last_name => "Last",
|
278
|
+
:hire_date => @today
|
279
|
+
)
|
280
|
+
@employee.reload
|
281
|
+
empl_id = @employee.id
|
282
|
+
lambda {
|
283
|
+
@employee.destroy
|
284
|
+
}.should raise_error("Make the transaction rollback")
|
274
285
|
@employee.id.should == empl_id
|
275
286
|
TestEmployee.find_by_employee_id(empl_id).should_not be_nil
|
276
287
|
ensure
|
@@ -278,10 +289,33 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
278
289
|
end
|
279
290
|
end
|
280
291
|
|
292
|
+
it "should set timestamps when creating record" do
|
293
|
+
@employee = TestEmployee.create(
|
294
|
+
:first_name => "First",
|
295
|
+
:last_name => "Last",
|
296
|
+
:hire_date => @today
|
297
|
+
)
|
298
|
+
@employee.created_at.should_not be_nil
|
299
|
+
@employee.updated_at.should_not be_nil
|
300
|
+
end
|
301
|
+
|
302
|
+
it "should set timestamps when updating record" do
|
303
|
+
@employee = TestEmployee.create(
|
304
|
+
:first_name => "First",
|
305
|
+
:last_name => "Last",
|
306
|
+
:hire_date => @today
|
307
|
+
)
|
308
|
+
@employee.reload
|
309
|
+
@employee.created_at.should be_nil
|
310
|
+
@employee.updated_at.should be_nil
|
311
|
+
@employee.first_name = "Second"
|
312
|
+
@employee.save!
|
313
|
+
@employee.created_at.should be_nil
|
314
|
+
@employee.updated_at.should_not be_nil
|
315
|
+
end
|
316
|
+
|
281
317
|
it "should log create record" do
|
282
318
|
log_to @buffer
|
283
|
-
# reestablish plsql.connection as log_to might reset existing connection
|
284
|
-
plsql.connection = ActiveRecord::Base.connection.raw_connection
|
285
319
|
@employee = TestEmployee.create(
|
286
320
|
:first_name => "First",
|
287
321
|
:last_name => "Last",
|
@@ -298,8 +332,6 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
298
332
|
:hire_date => @today
|
299
333
|
)
|
300
334
|
log_to @buffer
|
301
|
-
# reestablish plsql.connection as log_to might reset existing connection
|
302
|
-
plsql.connection = ActiveRecord::Base.connection.raw_connection
|
303
335
|
@employee.save!
|
304
336
|
@buffer.string.should match(/^TestEmployee Update \(\d+\.\d+(ms)?\) custom update method with employee_id=#{@employee.id}$/)
|
305
337
|
end
|
@@ -311,8 +343,6 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
|
|
311
343
|
:hire_date => @today
|
312
344
|
)
|
313
345
|
log_to @buffer
|
314
|
-
# reestablish plsql.connection as log_to might reset existing connection
|
315
|
-
plsql.connection = ActiveRecord::Base.connection.raw_connection
|
316
346
|
@employee.destroy
|
317
347
|
@buffer.string.should match(/^TestEmployee Destroy \(\d+\.\d+(ms)?\) custom delete method with employee_id=#{@employee.id}$/)
|
318
348
|
end
|
@@ -572,6 +572,7 @@ describe "OracleEnhancedAdapter schema definition" do
|
|
572
572
|
end
|
573
573
|
|
574
574
|
it "should add foreign key in change_table" do
|
575
|
+
return pending("Not in this ActiveRecord version") unless ENV['RAILS_GEM_VERSION'] >= '2.1'
|
575
576
|
schema_define do
|
576
577
|
create_table :test_comments, :force => true do |t|
|
577
578
|
t.string :body, :limit => 4000
|
@@ -587,6 +588,7 @@ describe "OracleEnhancedAdapter schema definition" do
|
|
587
588
|
end
|
588
589
|
|
589
590
|
it "should add foreign key in change_table references" do
|
591
|
+
return pending("Not in this ActiveRecord version") unless ENV['RAILS_GEM_VERSION'] >= '2.1'
|
590
592
|
schema_define do
|
591
593
|
create_table :test_comments, :force => true do |t|
|
592
594
|
t.string :body, :limit => 4000
|
@@ -601,6 +603,7 @@ describe "OracleEnhancedAdapter schema definition" do
|
|
601
603
|
end
|
602
604
|
|
603
605
|
it "should remove foreign key by table name" do
|
606
|
+
return pending("Not in this ActiveRecord version") unless ENV['RAILS_GEM_VERSION'] >= '2.1'
|
604
607
|
schema_define do
|
605
608
|
create_table :test_comments, :force => true do |t|
|
606
609
|
t.string :body, :limit => 4000
|
data/spec/spec_helper.rb
CHANGED
@@ -25,15 +25,15 @@ elsif ENV['RAILS_GEM_VERSION'] =~ /^2.3.3/
|
|
25
25
|
gem 'activesupport', '=2.3.3'
|
26
26
|
gem 'composite_primary_keys', '=2.3.2'
|
27
27
|
else
|
28
|
-
ENV['RAILS_GEM_VERSION'] ||= '2.3.
|
29
|
-
gem 'activerecord', '=2.3.
|
30
|
-
gem 'actionpack', '=2.3.
|
31
|
-
gem 'activesupport', '=2.3.
|
28
|
+
ENV['RAILS_GEM_VERSION'] ||= '2.3.5'
|
29
|
+
gem 'activerecord', '=2.3.5'
|
30
|
+
gem 'actionpack', '=2.3.5'
|
31
|
+
gem 'activesupport', '=2.3.5'
|
32
32
|
NO_COMPOSITE_PRIMARY_KEYS = true
|
33
33
|
end
|
34
34
|
|
35
|
-
require '
|
36
|
-
require '
|
35
|
+
require 'active_record'
|
36
|
+
require 'action_pack'
|
37
37
|
if ENV['RAILS_GEM_VERSION'] >= '2.3'
|
38
38
|
require 'action_controller/session/abstract_store'
|
39
39
|
require 'active_record/session_store'
|
@@ -42,14 +42,14 @@ else
|
|
42
42
|
end
|
43
43
|
if !defined?(RUBY_ENGINE)
|
44
44
|
# change version to 1.0.6 to test with old oracle_adapter
|
45
|
-
gem 'ruby-oci8', '
|
45
|
+
gem 'ruby-oci8', '=2.0.3'
|
46
46
|
require 'oci8'
|
47
47
|
if OCI8::VERSION =~ /^1\./
|
48
48
|
gem "activerecord-oracle-adapter"
|
49
49
|
require 'active_record/connection_adapters/oracle_adapter'
|
50
50
|
end
|
51
51
|
elsif RUBY_ENGINE == 'ruby'
|
52
|
-
gem 'ruby-oci8', '
|
52
|
+
gem 'ruby-oci8', '=2.0.3'
|
53
53
|
require 'oci8'
|
54
54
|
elsif RUBY_ENGINE == 'jruby'
|
55
55
|
gem "activerecord-jdbc-adapter"
|
@@ -123,3 +123,7 @@ SYSTEM_CONNECTION_PARAMS = {
|
|
123
123
|
|
124
124
|
# For JRuby Set default $KCODE to UTF8
|
125
125
|
$KCODE = "UTF8" if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
126
|
+
|
127
|
+
# set default time zone in TZ environment variable
|
128
|
+
# which will be used to set session time zone
|
129
|
+
ENV['TZ'] ||= 'Europe/Riga'
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Raimonds Simanovskis
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09
|
12
|
+
date: 2009-12-09 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -23,42 +23,34 @@ dependencies:
|
|
23
23
|
version: 2.0.0
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
26
|
+
name: rspec
|
27
27
|
type: :development
|
28
28
|
version_requirement:
|
29
29
|
version_requirements: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: 1.2.9
|
34
34
|
version:
|
35
|
-
description:
|
36
|
-
Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
See http://oracle-enhanced.rubyforge.org/rdoc for detailed API documentation.
|
42
|
-
|
43
|
-
For questions and feature discussion please use http://groups.google.com/group/oracle-enhanced
|
44
|
-
|
45
|
-
Blog posts about oracle-enahnced can be found at http://blog.rayapps.com/category/oracle-enhanced
|
46
|
-
|
47
|
-
Bugs and enhancement requests can be reported at http://rsim.lighthouseapp.com/projects/11468-oracle-enhanced
|
48
|
-
email:
|
49
|
-
- raimonds.simanovskis@gmail.com
|
35
|
+
description: |
|
36
|
+
Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases.
|
37
|
+
This adapter is superset of original ActiveRecord Oracle adapter.
|
38
|
+
|
39
|
+
email: raimonds.simanovskis@gmail.com
|
50
40
|
executables: []
|
51
41
|
|
52
42
|
extensions: []
|
53
43
|
|
54
44
|
extra_rdoc_files:
|
55
|
-
- History.txt
|
56
|
-
- License.txt
|
57
45
|
- README.rdoc
|
58
46
|
files:
|
47
|
+
- .gitignore
|
59
48
|
- History.txt
|
60
49
|
- License.txt
|
50
|
+
- Manifest.txt
|
61
51
|
- README.rdoc
|
52
|
+
- Rakefile
|
53
|
+
- VERSION
|
62
54
|
- lib/active_record/connection_adapters/emulation/oracle_adapter.rb
|
63
55
|
- lib/active_record/connection_adapters/oracle_enhanced.rake
|
64
56
|
- lib/active_record/connection_adapters/oracle_enhanced_adapter.rb
|
@@ -94,8 +86,7 @@ licenses: []
|
|
94
86
|
|
95
87
|
post_install_message:
|
96
88
|
rdoc_options:
|
97
|
-
- --
|
98
|
-
- README.rdoc
|
89
|
+
- --charset=UTF-8
|
99
90
|
require_paths:
|
100
91
|
- lib
|
101
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -112,10 +103,21 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
103
|
version:
|
113
104
|
requirements: []
|
114
105
|
|
115
|
-
rubyforge_project:
|
116
|
-
rubygems_version: 1.3.
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.3.5
|
117
108
|
signing_key:
|
118
109
|
specification_version: 3
|
119
|
-
summary: Oracle
|
120
|
-
test_files:
|
121
|
-
|
110
|
+
summary: Oracle enhanced adapter for ActiveRecord
|
111
|
+
test_files:
|
112
|
+
- spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb
|
113
|
+
- spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb
|
114
|
+
- spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb
|
115
|
+
- spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb
|
116
|
+
- spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb
|
117
|
+
- spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb
|
118
|
+
- spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb
|
119
|
+
- spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb
|
120
|
+
- spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb
|
121
|
+
- spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb
|
122
|
+
- spec/active_record/connection_adapters/oracle_enhanced_schema_spec.rb
|
123
|
+
- spec/spec_helper.rb
|