activerecord-oracle_enhanced-adapter 1.2.2 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|