activerecord-oracle_enhanced-adapter 1.5.4 → 1.5.5
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.
- checksums.yaml +4 -4
- data/History.md +14 -0
- data/VERSION +1 -1
- data/activerecord-oracle_enhanced-adapter.gemspec +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +37 -20
- data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +21 -4
- data/lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb +9 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +7 -7
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +1 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +5 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +25 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +4 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +55 -13
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +13 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +181 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1f1f3ee668e111001b017dd37db4d5e70bb315f
|
4
|
+
data.tar.gz: 10e4fdff8ab461b4e48ac248e8a61ccaa4fd1870
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58dddb4992f8ae81c79ee379d0c26a0dcfe869df5e052e1892679a9f03ba440b623fe7b6b2d6c4a85e589bc80989b47e1285d8ad9139e19a64e249872701d566
|
7
|
+
data.tar.gz: d42acd789d7733e82e7e70d8c81c453e9dbd0a3a3dc0b196901ed9552ad09580540559ee5dbb0ec30102ef83d389b313ba932bfe22dc5c7ef0cefda1347ff1db
|
data/History.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 1.5.5 / 2014-05-23
|
2
|
+
|
3
|
+
* Enhancements
|
4
|
+
* Oracle NUMBER datatype can be handled as Rails :float datatype [#418]
|
5
|
+
- Default NUMBER datatype handled as :decimal to keep compatibility
|
6
|
+
- Configured by setting `self.number_datatype_coercion = :float`
|
7
|
+
* Add link to supported Oracle database version, JDK and Oracle JDBC Driver version [#438]
|
8
|
+
* Support `without_prepared_statements?` to handle `unprepared_statement` [#447]
|
9
|
+
|
10
|
+
* Bug Fix
|
11
|
+
* Associations with name `record` do not work correctly since Rails 4 [#435]
|
12
|
+
* Skip another Oracle Text test when Oracle 12c used [#437]
|
13
|
+
* Tag bind params with a bind param object [#444]
|
14
|
+
|
1
15
|
## 1.5.4 / 2014-03-25
|
2
16
|
|
3
17
|
* Enhancements
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.5.
|
1
|
+
1.5.5
|
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{activerecord-oracle_enhanced-adapter}
|
8
|
-
s.version = "1.5.
|
8
|
+
s.version = "1.5.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.license = 'MIT'
|
12
12
|
s.authors = [%q{Raimonds Simanovskis}]
|
13
|
-
s.date = %q{2014-
|
13
|
+
s.date = %q{2014-05-23}
|
14
14
|
s.description = %q{Oracle "enhanced" ActiveRecord adapter contains useful additional methods for working with new and legacy Oracle databases.
|
15
15
|
This adapter is superset of original ActiveRecord Oracle adapter.
|
16
16
|
}
|
@@ -271,6 +271,13 @@ module ActiveRecord
|
|
271
271
|
cattr_accessor :emulate_dates_by_column_name
|
272
272
|
self.emulate_dates_by_column_name = false
|
273
273
|
|
274
|
+
##
|
275
|
+
# :singleton-method:
|
276
|
+
# Specify how `NUMBER` datatype columns, without precision and scale, are handled in Rails world.
|
277
|
+
# Default is :decimal and other valid option is :float. Be wary of setting it to other values.
|
278
|
+
cattr_accessor :number_datatype_coercion
|
279
|
+
self.number_datatype_coercion = :decimal
|
280
|
+
|
274
281
|
# Check column name to identify if it is Date (and not Time) column.
|
275
282
|
# Is used if +emulate_dates_by_column_name+ option is set to +true+.
|
276
283
|
# Override this method definition in initializer file if different Date column recognition is needed.
|
@@ -305,7 +312,7 @@ module ActiveRecord
|
|
305
312
|
# Is used if +emulate_integers_by_column_name+ option is set to +true+.
|
306
313
|
# Override this method definition in initializer file if different Integer column recognition is needed.
|
307
314
|
def self.is_integer_column?(name, table_name = nil)
|
308
|
-
name =~ /(^|_)id$/i
|
315
|
+
!!(name =~ /(^|_)id$/i)
|
309
316
|
end
|
310
317
|
|
311
318
|
##
|
@@ -389,6 +396,7 @@ module ActiveRecord
|
|
389
396
|
@enable_dbms_output = false
|
390
397
|
if config.fetch(:prepared_statements) { true }
|
391
398
|
@visitor = Arel::Visitors::Oracle.new self
|
399
|
+
@prepared_statements = true
|
392
400
|
else
|
393
401
|
@visitor = unprepared_visitor
|
394
402
|
end
|
@@ -420,6 +428,8 @@ module ActiveRecord
|
|
420
428
|
true
|
421
429
|
end
|
422
430
|
|
431
|
+
NUMBER_MAX_PRECISION = 38
|
432
|
+
|
423
433
|
#:stopdoc:
|
424
434
|
DEFAULT_NLS_PARAMETERS = {
|
425
435
|
:nls_calendar => nil,
|
@@ -443,10 +453,10 @@ module ActiveRecord
|
|
443
453
|
|
444
454
|
#:stopdoc:
|
445
455
|
NATIVE_DATABASE_TYPES = {
|
446
|
-
:primary_key => "NUMBER(
|
456
|
+
:primary_key => "NUMBER(#{NUMBER_MAX_PRECISION}) NOT NULL PRIMARY KEY",
|
447
457
|
:string => { :name => "VARCHAR2", :limit => 255 },
|
448
458
|
:text => { :name => "CLOB" },
|
449
|
-
:integer => { :name => "NUMBER", :limit =>
|
459
|
+
:integer => { :name => "NUMBER", :limit => NUMBER_MAX_PRECISION },
|
450
460
|
:float => { :name => "NUMBER" },
|
451
461
|
:decimal => { :name => "DECIMAL" },
|
452
462
|
:datetime => { :name => "DATE" },
|
@@ -728,7 +738,7 @@ module ActiveRecord
|
|
728
738
|
end
|
729
739
|
|
730
740
|
def substitute_at(column, index)
|
731
|
-
Arel.
|
741
|
+
Arel::Nodes::BindParam.new (":a#{index + 1}")
|
732
742
|
end
|
733
743
|
|
734
744
|
def clear_cache!
|
@@ -742,7 +752,7 @@ module ActiveRecord
|
|
742
752
|
log(sql, name, type_casted_binds) do
|
743
753
|
cursor = nil
|
744
754
|
cached = false
|
745
|
-
if binds
|
755
|
+
if without_prepared_statement?(binds)
|
746
756
|
cursor = @connection.prepare(sql)
|
747
757
|
else
|
748
758
|
unless @statements.key? sql
|
@@ -834,22 +844,29 @@ module ActiveRecord
|
|
834
844
|
|
835
845
|
# New method in ActiveRecord 3.1
|
836
846
|
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
837
|
-
|
847
|
+
type_casted_binds = binds.map { |col, val|
|
848
|
+
[col, type_cast(val, col)]
|
849
|
+
}
|
850
|
+
log(sql, name, type_casted_binds) do
|
838
851
|
returning_id_col = returning_id_index = nil
|
839
|
-
|
840
|
-
@
|
852
|
+
if without_prepared_statement?(binds)
|
853
|
+
cursor = @connection.prepare(sql)
|
841
854
|
else
|
842
|
-
@statements
|
843
|
-
|
855
|
+
unless @statements.key? (sql)
|
856
|
+
@statements[sql] = @connection.prepare(sql)
|
857
|
+
end
|
844
858
|
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
859
|
+
cursor = @statements[sql]
|
860
|
+
|
861
|
+
binds.each_with_index do |bind, i|
|
862
|
+
col, val = bind
|
863
|
+
if col.returning_id?
|
864
|
+
returning_id_col = [col]
|
865
|
+
returning_id_index = i + 1
|
866
|
+
cursor.bind_returning_param(returning_id_index, Integer)
|
867
|
+
else
|
868
|
+
cursor.bind_param(i + 1, type_cast(val, col), col)
|
869
|
+
end
|
853
870
|
end
|
854
871
|
end
|
855
872
|
|
@@ -868,7 +885,7 @@ module ActiveRecord
|
|
868
885
|
def exec_update(sql, name, binds)
|
869
886
|
log(sql, name, binds) do
|
870
887
|
cached = false
|
871
|
-
if binds
|
888
|
+
if without_prepared_statement?(binds)
|
872
889
|
cursor = @connection.prepare(sql)
|
873
890
|
else
|
874
891
|
cursor = if @statements.key?(sql)
|
@@ -1260,7 +1277,7 @@ module ActiveRecord
|
|
1260
1277
|
end.map do |row|
|
1261
1278
|
limit, scale = row['limit'], row['scale']
|
1262
1279
|
if limit || scale
|
1263
|
-
row['sql_type'] += "(#{(limit ||
|
1280
|
+
row['sql_type'] += "(#{(limit || NUMBER_MAX_PRECISION).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
|
1264
1281
|
end
|
1265
1282
|
|
1266
1283
|
if row['sql_type_owner']
|
@@ -23,9 +23,24 @@ module ActiveRecord
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def type_cast(value) #:nodoc:
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
case type
|
27
|
+
when :raw
|
28
|
+
OracleEnhancedColumn.string_to_raw(value)
|
29
|
+
when :datetime
|
30
|
+
OracleEnhancedAdapter.emulate_dates ? guess_date_or_time(value) : super
|
31
|
+
when :float
|
32
|
+
!value.nil? ? self.class.value_to_decimal(value) : super
|
33
|
+
else
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def type_cast_code(var_name)
|
39
|
+
type == :float ? "#{self.class.name}.value_to_decimal(#{var_name})" : super
|
40
|
+
end
|
41
|
+
|
42
|
+
def klass
|
43
|
+
type == :float ? BigDecimal : super
|
29
44
|
end
|
30
45
|
|
31
46
|
def virtual?
|
@@ -85,12 +100,14 @@ module ActiveRecord
|
|
85
100
|
forced_column_type ||
|
86
101
|
case field_type
|
87
102
|
when /decimal|numeric|number/i
|
88
|
-
if OracleEnhancedAdapter.emulate_booleans && field_type ==
|
103
|
+
if OracleEnhancedAdapter.emulate_booleans && field_type.upcase == "NUMBER(1)"
|
89
104
|
:boolean
|
90
105
|
elsif extract_scale(field_type) == 0 ||
|
91
106
|
# if column name is ID or ends with _ID
|
92
107
|
OracleEnhancedAdapter.emulate_integers_by_column_name && OracleEnhancedAdapter.is_integer_column?(name, table_name)
|
93
108
|
:integer
|
109
|
+
elsif field_type.upcase == "NUMBER"
|
110
|
+
OracleEnhancedAdapter.number_datatype_coercion
|
94
111
|
else
|
95
112
|
:decimal
|
96
113
|
end
|
@@ -39,15 +39,23 @@ module ActiveRecord #:nodoc:
|
|
39
39
|
return prepare_column_options_without_oracle_enhanced(column, types) unless oracle_enhanced_adapter?
|
40
40
|
|
41
41
|
spec = {}
|
42
|
+
|
42
43
|
spec[:name] = column.name.inspect
|
43
44
|
spec[:type] = column.virtual? ? 'virtual' : column.type.to_s
|
44
|
-
spec[:virtual_type] = column.type.inspect if column.virtual? && column.sql_type != 'NUMBER'
|
45
45
|
spec[:limit] = column.limit.inspect if column.limit != types[column.type][:limit] && column.type != :decimal
|
46
46
|
spec[:precision] = column.precision.inspect if !column.precision.nil?
|
47
47
|
spec[:scale] = column.scale.inspect if !column.scale.nil?
|
48
48
|
spec[:null] = 'false' if !column.null
|
49
49
|
spec[:as] = column.virtual_column_data_default if column.virtual?
|
50
50
|
spec[:default] = default_string(column.default) if column.has_default? && !column.virtual?
|
51
|
+
|
52
|
+
if column.virtual?
|
53
|
+
# Supports backwards compatibility with older OracleEnhancedAdapter versions where 'NUMBER' virtual column type is not included in dump
|
54
|
+
if column.sql_type != "NUMBER" || ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.number_datatype_coercion != :decimal
|
55
|
+
spec[:virtual_type] = column.type.inspect
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
51
59
|
spec
|
52
60
|
end
|
53
61
|
|
@@ -4,19 +4,19 @@ module ActiveRecord #:nodoc:
|
|
4
4
|
|
5
5
|
module InstanceMethods #:nodoc:
|
6
6
|
private
|
7
|
-
|
7
|
+
|
8
8
|
def _field_changed?(attr, old, value)
|
9
9
|
if column = column_for_attribute(attr)
|
10
10
|
# Added also :decimal type
|
11
|
-
if (
|
12
|
-
# For nullable integer columns, NULL gets stored in database for blank (i.e. '') values.
|
11
|
+
if ([:integer, :decimal, :float].include? column.type) && column.null && (old.nil? || old == 0) && value.blank?
|
12
|
+
# For nullable integer/decimal/float columns, NULL gets stored in database for blank (i.e. '') values.
|
13
13
|
# Hence we don't record it as a change if the value changes from nil to ''.
|
14
14
|
# If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll
|
15
15
|
# be typecast back to 0 (''.to_i => 0)
|
16
16
|
value = nil
|
17
|
-
# Oracle stores empty string '' as NULL
|
18
|
-
# therefore need to convert empty string value to nil if old value is nil
|
19
17
|
elsif column.type == :string && column.null && old.nil?
|
18
|
+
# Oracle stores empty string '' as NULL
|
19
|
+
# therefore need to convert empty string value to nil if old value is nil
|
20
20
|
value = nil if value == ''
|
21
21
|
elsif old == 0 && value.is_a?(String) && value.present? && non_zero?(value)
|
22
22
|
value = nil
|
@@ -30,8 +30,8 @@ module ActiveRecord #:nodoc:
|
|
30
30
|
|
31
31
|
def non_zero?(value)
|
32
32
|
value !~ /\A0+(\.0+)?\z/
|
33
|
-
end
|
34
|
-
|
33
|
+
end
|
34
|
+
|
35
35
|
end
|
36
36
|
|
37
37
|
end
|
@@ -27,6 +27,7 @@ begin
|
|
27
27
|
ojdbc_jars.any? do |ojdbc_jar|
|
28
28
|
if File.exists?(file_path = File.join(dir, ojdbc_jar))
|
29
29
|
puts "WARNING: JDK #{java_version} is not officially supported by #{ojdbc_jar}" if java_version >= '1.8'
|
30
|
+
puts "See http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#01_03 for supported versions"
|
30
31
|
require file_path
|
31
32
|
true
|
32
33
|
end
|
@@ -98,7 +98,7 @@ module ActiveRecord #:nodoc:
|
|
98
98
|
|
99
99
|
# Creates a record with custom create method
|
100
100
|
# and returns its id.
|
101
|
-
def
|
101
|
+
def _create_record
|
102
102
|
# check if class has custom create method
|
103
103
|
if self.class.custom_create_method
|
104
104
|
# run before/after callbacks defined in model
|
@@ -133,7 +133,7 @@ module ActiveRecord #:nodoc:
|
|
133
133
|
|
134
134
|
# Updates the associated record with custom update method
|
135
135
|
# Returns the number of affected rows.
|
136
|
-
def
|
136
|
+
def _update_record(attribute_names = @attributes.keys)
|
137
137
|
# check if class has custom update method
|
138
138
|
if self.class.custom_update_method
|
139
139
|
# run before/after callbacks defined in model
|
@@ -187,5 +187,8 @@ module ActiveRecord #:nodoc:
|
|
187
187
|
def log_custom_method(*args)
|
188
188
|
self.class.connection.send(:log, *args) { yield }
|
189
189
|
end
|
190
|
+
|
191
|
+
alias_method :update_record, :_update_record if private_method_defined?(:_update_record)
|
192
|
+
alias_method :create_record, :_create_record if private_method_defined?(:_create_record)
|
190
193
|
end
|
191
194
|
end
|
@@ -686,4 +686,29 @@ describe "OracleEnhancedAdapter" do
|
|
686
686
|
explain.should include("INDEX UNIQUE SCAN")
|
687
687
|
end
|
688
688
|
end if ENV['RAILS_GEM_VERSION'] >= '3.2'
|
689
|
+
|
690
|
+
describe ".is_integer_column?" do
|
691
|
+
before(:all) do
|
692
|
+
@adapter = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
|
693
|
+
end
|
694
|
+
|
695
|
+
it "should return TrueClass or FalseClass" do
|
696
|
+
@adapter.is_integer_column?("adapter_id").should be_a TrueClass
|
697
|
+
@adapter.is_integer_column?("").should be_a FalseClass
|
698
|
+
end
|
699
|
+
|
700
|
+
it "should return true if name is 'id'" do
|
701
|
+
@adapter.is_integer_column?("id").should be_true
|
702
|
+
end
|
703
|
+
|
704
|
+
it "should return true if name ends with '_id'" do
|
705
|
+
@adapter.is_integer_column?("_id").should be_true
|
706
|
+
@adapter.is_integer_column?("foo_id").should be_true
|
707
|
+
end
|
708
|
+
|
709
|
+
it "should return false if name is 'something_else'" do
|
710
|
+
@adapter.is_integer_column?("something_else").should be_false
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
689
714
|
end
|
@@ -381,6 +381,9 @@ describe "OracleEnhancedAdapter context index" do
|
|
381
381
|
|
382
382
|
describe "with table prefix and suffix" do
|
383
383
|
before(:all) do
|
384
|
+
@conn = ActiveRecord::Base.connection
|
385
|
+
@oracle12c = !! @conn.select_value(
|
386
|
+
"select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) = 12")
|
384
387
|
ActiveRecord::Base.table_name_prefix = 'xxx_'
|
385
388
|
ActiveRecord::Base.table_name_suffix = '_xxx'
|
386
389
|
create_tables
|
@@ -405,6 +408,7 @@ describe "OracleEnhancedAdapter context index" do
|
|
405
408
|
end
|
406
409
|
|
407
410
|
it "should dump definition of multiple table index with options" do
|
411
|
+
pending "It always fails when Oracle 12c 12.1.0 used." if @oracle12c
|
408
412
|
options = {
|
409
413
|
name: 'xxx_post_and_comments_i',
|
410
414
|
index_column: :all_text, index_column_trigger_on: :updated_at,
|
@@ -206,6 +206,7 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
206
206
|
job_id NUMBER,
|
207
207
|
salary NUMBER,
|
208
208
|
commission_pct NUMBER(2,2),
|
209
|
+
unwise_name_id NUMBER(2,2),
|
209
210
|
manager_id NUMBER(6),
|
210
211
|
is_manager NUMBER(1),
|
211
212
|
department_id NUMBER(4,0),
|
@@ -218,17 +219,46 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
218
219
|
INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
|
219
220
|
SQL
|
220
221
|
end
|
221
|
-
|
222
|
+
|
222
223
|
after(:all) do
|
223
224
|
@conn.execute "DROP TABLE test2_employees"
|
224
225
|
@conn.execute "DROP SEQUENCE test2_employees_seq"
|
225
226
|
end
|
226
227
|
|
227
|
-
|
228
|
-
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.
|
229
|
-
|
230
|
-
column
|
231
|
-
|
228
|
+
context "when number_datatype_coercion is :decimal" do
|
229
|
+
before { ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion).and_return(:decimal) }
|
230
|
+
|
231
|
+
it "should set NUMBER column type as decimal if emulate_integers_by_column_name is false" do
|
232
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
|
233
|
+
columns = @conn.columns('test2_employees')
|
234
|
+
column = columns.detect{|c| c.name == "job_id"}
|
235
|
+
column.type.should == :decimal
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should set NUMBER column type as decimal if column name is not 'id' and does not ends with '_id' and emulate_integers_by_column_name is true" do
|
239
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
|
240
|
+
columns = @conn.columns('test2_employees')
|
241
|
+
column = columns.detect{|c| c.name == "salary"}
|
242
|
+
column.type.should == :decimal
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context "when number_datatype_coercion is :float" do
|
247
|
+
before { ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion).and_return(:float) }
|
248
|
+
|
249
|
+
it "should set NUMBER column type as float if emulate_integers_by_column_name is false" do
|
250
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
|
251
|
+
columns = @conn.columns('test2_employees')
|
252
|
+
column = columns.detect{|c| c.name == "job_id"}
|
253
|
+
column.type.should == :float
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should set NUMBER column type as float if column name is not 'id' and does not ends with '_id' and emulate_integers_by_column_name is true" do
|
257
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
|
258
|
+
columns = @conn.columns('test2_employees')
|
259
|
+
column = columns.detect{|c| c.name == "salary"}
|
260
|
+
column.type.should == :float
|
261
|
+
end
|
232
262
|
end
|
233
263
|
|
234
264
|
it "should set NUMBER column type as integer if emulate_integers_by_column_name is true" do
|
@@ -240,10 +270,24 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
240
270
|
column.type.should == :integer
|
241
271
|
end
|
242
272
|
|
243
|
-
it "should set NUMBER column type as
|
273
|
+
it "should set NUMBER(p,0) column type as integer" do
|
244
274
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
|
245
275
|
columns = @conn.columns('test2_employees')
|
246
|
-
column = columns.detect{|c| c.name == "
|
276
|
+
column = columns.detect{|c| c.name == "department_id"}
|
277
|
+
column.type.should == :integer
|
278
|
+
end
|
279
|
+
|
280
|
+
it "should set NUMBER(p,s) column type as integer if column name ends with '_id' and emulate_integers_by_column_name is true" do
|
281
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
|
282
|
+
columns = @conn.columns('test2_employees')
|
283
|
+
column = columns.detect{|c| c.name == "unwise_name_id"}
|
284
|
+
column.type.should == :integer
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should set NUMBER(p,s) column type as decimal if column name ends with '_id' and emulate_integers_by_column_name is false" do
|
288
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = false
|
289
|
+
columns = @conn.columns('test2_employees')
|
290
|
+
column = columns.detect{|c| c.name == "unwise_name_id"}
|
247
291
|
column.type.should == :decimal
|
248
292
|
end
|
249
293
|
|
@@ -254,7 +298,7 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
254
298
|
column.type_cast(1.0).class.should == BigDecimal
|
255
299
|
end
|
256
300
|
|
257
|
-
it "should return Fixnum value from NUMBER column if column name
|
301
|
+
it "should return Fixnum value from NUMBER column if column name ends with '_id' and emulate_integers_by_column_name is true" do
|
258
302
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
|
259
303
|
columns = @conn.columns('test2_employees')
|
260
304
|
column = columns.detect{|c| c.name == "job_id"}
|
@@ -266,7 +310,7 @@ describe "OracleEnhancedAdapter integer type detection based on column names" do
|
|
266
310
|
class ::Test2Employee < ActiveRecord::Base
|
267
311
|
end
|
268
312
|
end
|
269
|
-
|
313
|
+
|
270
314
|
after(:each) do
|
271
315
|
Object.send(:remove_const, "Test2Employee")
|
272
316
|
@conn.clear_types_for_columns
|
@@ -606,7 +650,6 @@ describe "OracleEnhancedAdapter timestamp with timezone support" do
|
|
606
650
|
|
607
651
|
end
|
608
652
|
|
609
|
-
|
610
653
|
describe "OracleEnhancedAdapter date and timestamp with different NLS date formats" do
|
611
654
|
before(:all) do
|
612
655
|
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
@@ -863,7 +906,7 @@ describe "OracleEnhancedAdapter assign string to :date and :datetime columns" do
|
|
863
906
|
@employee.reload
|
864
907
|
@employee.last_login_at.should == @today.to_time
|
865
908
|
end
|
866
|
-
|
909
|
+
|
867
910
|
end
|
868
911
|
|
869
912
|
describe "OracleEnhancedAdapter handling of CLOB columns" do
|
@@ -1301,7 +1344,6 @@ describe "OracleEnhancedAdapter handling of RAW columns" do
|
|
1301
1344
|
end
|
1302
1345
|
end
|
1303
1346
|
|
1304
|
-
|
1305
1347
|
describe "OracleEnhancedAdapter quoting of NCHAR and NVARCHAR2 columns" do
|
1306
1348
|
before(:all) do
|
1307
1349
|
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
@@ -16,6 +16,7 @@ if ActiveRecord::Base.method_defined?(:changed?)
|
|
16
16
|
last_name VARCHAR2(25),
|
17
17
|
job_id NUMBER(6,0) NULL,
|
18
18
|
salary NUMBER(8,2),
|
19
|
+
pto_per_hour NUMBER,
|
19
20
|
comments CLOB,
|
20
21
|
hire_date DATE
|
21
22
|
)
|
@@ -27,7 +28,7 @@ if ActiveRecord::Base.method_defined?(:changed?)
|
|
27
28
|
class TestEmployee < ActiveRecord::Base
|
28
29
|
end
|
29
30
|
end
|
30
|
-
|
31
|
+
|
31
32
|
after(:all) do
|
32
33
|
Object.send(:remove_const, "TestEmployee")
|
33
34
|
@conn.execute "DROP TABLE test_employees"
|
@@ -62,6 +63,16 @@ if ActiveRecord::Base.method_defined?(:changed?)
|
|
62
63
|
@employee.should_not be_changed
|
63
64
|
end
|
64
65
|
|
66
|
+
it "should not mark empty float (stored as NULL) as changed when reassigning it" do
|
67
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion) { :float }
|
68
|
+
@employee = TestEmployee.create!(:pto_per_hour => '')
|
69
|
+
@employee.pto_per_hour = ''
|
70
|
+
@employee.should_not be_changed
|
71
|
+
@employee.reload
|
72
|
+
@employee.pto_per_hour = ''
|
73
|
+
@employee.should_not be_changed
|
74
|
+
end
|
75
|
+
|
65
76
|
it "should not mark empty text (stored as NULL) as changed when reassigning it" do
|
66
77
|
@employee = TestEmployee.create!(:comments => nil)
|
67
78
|
@employee.comments = nil
|
@@ -111,7 +122,7 @@ if ActiveRecord::Base.method_defined?(:changed?)
|
|
111
122
|
@employee = TestEmployee.new
|
112
123
|
@employee.job_id = 0
|
113
124
|
@employee.save!.should be_true
|
114
|
-
|
125
|
+
|
115
126
|
@employee.should_not be_changed
|
116
127
|
|
117
128
|
@employee.job_id = '0'
|
@@ -376,7 +376,7 @@ describe "OracleEnhancedAdapter schema dump" do
|
|
376
376
|
t.virtual :full_name, :as => "first_name || ', ' || last_name"
|
377
377
|
t.virtual :short_name, :as => "COALESCE(first_name, last_name)", :type => :string, :limit => 300
|
378
378
|
t.virtual :abbrev_name, :as => "SUBSTR(first_name,1,50) || ' ' || SUBSTR(last_name,1,1) || '.'", :type => "VARCHAR(100)"
|
379
|
-
t.virtual :name_ratio, :as=>'(LENGTH(first_name)
|
379
|
+
t.virtual :name_ratio, :as=>'(LENGTH(first_name)/LENGTH(last_name))'
|
380
380
|
t.column :full_name_length, :virtual, :as => "length(first_name || ', ' || last_name)", :type => :integer
|
381
381
|
t.virtual :field_with_leading_space, :as => "' ' || first_name || ' '", :limit => 300, :type => :string
|
382
382
|
end
|
@@ -402,13 +402,30 @@ describe "OracleEnhancedAdapter schema dump" do
|
|
402
402
|
end
|
403
403
|
end
|
404
404
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
405
|
+
context "when number_datatype_coercion is :float" do
|
406
|
+
before { ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion).and_return(:float) }
|
407
|
+
|
408
|
+
it 'should dump correctly' do
|
409
|
+
standard_dump.should =~ /t\.virtual "full_name",(\s*)limit: 512,(\s*)as: "\\"FIRST_NAME\\"\|\|', '\|\|\\"LAST_NAME\\"",(\s*)type: :string/
|
410
|
+
standard_dump.should =~ /t\.virtual "short_name",(\s*)limit: 300,(\s*)as:(.*),(\s*)type: :string/
|
411
|
+
standard_dump.should =~ /t\.virtual "full_name_length",(\s*)precision: 38,(\s*)scale: 0,(\s*)as:(.*),(\s*)type: :integer/
|
412
|
+
standard_dump.should =~ /t\.virtual "name_ratio",(\s*)as:(.*),(\s*)type: :float$/
|
413
|
+
standard_dump.should =~ /t\.virtual "abbrev_name",(\s*)limit: 100,(\s*)as:(.*),(\s*)type: :string/
|
414
|
+
standard_dump.should =~ /t\.virtual "field_with_leading_space",(\s*)limit: 300,(\s*)as: "' '\|\|\\"FIRST_NAME\\"\|\|' '",(\s*)type: :string/
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
context "when number_datatype_coercion is :decimal" do
|
419
|
+
before { ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion).and_return(:decimal) }
|
420
|
+
|
421
|
+
it 'should dump correctly' do
|
422
|
+
standard_dump.should =~ /t\.virtual "full_name",(\s*)limit: 512,(\s*)as: "\\"FIRST_NAME\\"\|\|', '\|\|\\"LAST_NAME\\"",(\s*)type: :string/
|
423
|
+
standard_dump.should =~ /t\.virtual "short_name",(\s*)limit: 300,(\s*)as:(.*),(\s*)type: :string/
|
424
|
+
standard_dump.should =~ /t\.virtual "full_name_length",(\s*)precision: 38,(\s*)scale: 0,(\s*)as:(.*),(\s*)type: :integer/
|
425
|
+
standard_dump.should =~ /t\.virtual "name_ratio",(\s*)as:(.*)\"$/
|
426
|
+
standard_dump.should =~ /t\.virtual "abbrev_name",(\s*)limit: 100,(\s*)as:(.*),(\s*)type: :string/
|
427
|
+
standard_dump.should =~ /t\.virtual "field_with_leading_space",(\s*)limit: 300,(\s*)as: "' '\|\|\\"FIRST_NAME\\"\|\|' '",(\s*)type: :string/
|
428
|
+
end
|
412
429
|
end
|
413
430
|
|
414
431
|
context 'with column cache' do
|
@@ -454,4 +471,160 @@ describe "OracleEnhancedAdapter schema dump" do
|
|
454
471
|
end
|
455
472
|
end
|
456
473
|
|
474
|
+
describe "NUMBER columns" do
|
475
|
+
after(:each) do
|
476
|
+
schema_define do
|
477
|
+
drop_table "test_numbers"
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
let(:value_within_max_precision) { (10 ** @conn.class::NUMBER_MAX_PRECISION) - 1 }
|
482
|
+
let(:value_exceeding_max_precision) { (10 ** @conn.class::NUMBER_MAX_PRECISION) + 1 }
|
483
|
+
|
484
|
+
context "when using ActiveRecord::Schema.define and ActiveRecord::ConnectionAdapters::TableDefinition#float" do
|
485
|
+
before :each do
|
486
|
+
schema_define do
|
487
|
+
create_table :test_numbers, :force => true do |t|
|
488
|
+
t.float :value
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
context "when number_datatype_coercion is :float" do
|
494
|
+
before { ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion).and_return(:float) }
|
495
|
+
|
496
|
+
it "should dump correctly" do
|
497
|
+
standard_dump.should =~ /t\.float "value"$/
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
context "when number_datatype_coercion is :decimal" do
|
502
|
+
before { ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion).and_return(:decimal) }
|
503
|
+
|
504
|
+
it "should dump correctly" do
|
505
|
+
standard_dump.should =~ /t\.decimal "value"$/
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
context "when using handwritten 'CREATE_TABLE' SQL" do
|
511
|
+
before :each do
|
512
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
513
|
+
@conn = ActiveRecord::Base.connection
|
514
|
+
@conn.execute <<-SQL
|
515
|
+
CREATE TABLE test_numbers (
|
516
|
+
id NUMBER(#{@conn.class::NUMBER_MAX_PRECISION},0) PRIMARY KEY,
|
517
|
+
value NUMBER
|
518
|
+
)
|
519
|
+
SQL
|
520
|
+
@conn.execute <<-SQL
|
521
|
+
CREATE SEQUENCE test_numbers_seq MINVALUE 1
|
522
|
+
INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE
|
523
|
+
SQL
|
524
|
+
end
|
525
|
+
|
526
|
+
context "when number_datatype_coercion is :float" do
|
527
|
+
before { ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion).and_return(:float) }
|
528
|
+
|
529
|
+
it "should dump correctly" do
|
530
|
+
standard_dump.should =~ /t\.float "value"$/
|
531
|
+
end
|
532
|
+
|
533
|
+
describe "ActiveRecord saving" do
|
534
|
+
before :each do
|
535
|
+
class ::TestNumber < ActiveRecord::Base
|
536
|
+
self.table_name = "test_numbers"
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
it "should allow saving of values within NUMBER_MAX_PRECISION" do
|
541
|
+
number = TestNumber.new(value: value_within_max_precision)
|
542
|
+
number.save!
|
543
|
+
number.reload
|
544
|
+
number.value.should eq(value_within_max_precision)
|
545
|
+
end
|
546
|
+
|
547
|
+
it "should allow saving of values larger than NUMBER_MAX_PRECISION" do
|
548
|
+
number = TestNumber.new(value: value_exceeding_max_precision)
|
549
|
+
number.save!
|
550
|
+
number.reload
|
551
|
+
number.value.should eq(value_exceeding_max_precision)
|
552
|
+
end
|
553
|
+
|
554
|
+
it "should be recreatable from dump and have same properties" do
|
555
|
+
# Simulating db:schema:dump & db:test:load
|
556
|
+
2.times do
|
557
|
+
create_table_dump = standard_dump[/(create_table.+?end)/m]
|
558
|
+
|
559
|
+
schema_define do
|
560
|
+
drop_table "test_numbers"
|
561
|
+
end
|
562
|
+
|
563
|
+
schema_define(&eval("-> * { #{create_table_dump} }"))
|
564
|
+
end
|
565
|
+
|
566
|
+
number = TestNumber.new(value: value_within_max_precision)
|
567
|
+
number.save!
|
568
|
+
|
569
|
+
number2 = TestNumber.new(value: value_exceeding_max_precision)
|
570
|
+
number2.save!
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
context "when number_datatype_coercion is :decimal" do
|
576
|
+
before { ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.stub(:number_datatype_coercion).and_return(:decimal) }
|
577
|
+
|
578
|
+
it "should dump correctly" do
|
579
|
+
standard_dump.should =~ /t\.decimal "value"$/
|
580
|
+
end
|
581
|
+
|
582
|
+
describe "ActiveRecord saving" do
|
583
|
+
before :each do
|
584
|
+
class ::TestNumber < ActiveRecord::Base
|
585
|
+
self.table_name = "test_numbers"
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
it "should allow saving of values within NUMBER_MAX_PRECISION" do
|
590
|
+
number = TestNumber.new(value: value_within_max_precision)
|
591
|
+
number.save!
|
592
|
+
number.reload
|
593
|
+
number.value.should eq(value_within_max_precision)
|
594
|
+
end
|
595
|
+
|
596
|
+
it "should allow saving of values larger than NUMBER_MAX_PRECISION" do
|
597
|
+
number = TestNumber.new(value: value_exceeding_max_precision)
|
598
|
+
number.save!
|
599
|
+
number.reload
|
600
|
+
number.value.should eq(value_exceeding_max_precision)
|
601
|
+
end
|
602
|
+
|
603
|
+
it "should be recreatable from dump and have same properties" do
|
604
|
+
# Simulating db:schema:dump & db:test:load
|
605
|
+
2.times do |i|
|
606
|
+
create_table_dump = standard_dump[/(create_table.+?end)/m]
|
607
|
+
|
608
|
+
schema_define do
|
609
|
+
drop_table "test_numbers"
|
610
|
+
end
|
611
|
+
|
612
|
+
schema_define(&eval("-> * { #{create_table_dump} }"))
|
613
|
+
end
|
614
|
+
|
615
|
+
number = TestNumber.new(value: value_within_max_precision)
|
616
|
+
number.save!
|
617
|
+
|
618
|
+
# Raises 'ORA-01438' as :value column type isn't FLOAT'ish
|
619
|
+
number2 = TestNumber.new(value: value_exceeding_max_precision)
|
620
|
+
lambda do
|
621
|
+
number2.save!
|
622
|
+
end.should raise_error() { |e| e.message.should =~ /ORA-01438/ }
|
623
|
+
end
|
624
|
+
end
|
625
|
+
end # context (:decimal)
|
626
|
+
|
627
|
+
end # context (handwritten)
|
628
|
+
end # describe (NUMBER columns)
|
629
|
+
|
457
630
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-oracle_enhanced-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Raimonds Simanovskis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jeweler
|