activerecord-oracle_enhanced-adapter 7.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +56 -0
- data/README.md +0 -1
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +5 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +35 -27
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +15 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +9 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +24 -15
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +7 -5
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +5 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +24 -22
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +17 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +72 -29
- data/lib/activerecord-oracle_enhanced-adapter.rb +8 -0
- data/lib/arel/visitors/oracle.rb +6 -3
- data/lib/arel/visitors/oracle12.rb +6 -5
- data/lib/arel/visitors/oracle_common.rb +46 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +24 -5
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +7 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +2 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +3 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +25 -15
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +15 -18
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +14 -10
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +2 -2
- data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +24 -0
- data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +4 -2
- data/spec/active_record/oracle_enhanced/type/integer_spec.rb +8 -0
- data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +3 -3
- data/spec/active_record/oracle_enhanced/type/raw_spec.rb +15 -0
- data/spec/active_record/oracle_enhanced/type/text_spec.rb +18 -3
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +5 -1
- data/spec/spec_config.yaml.template +2 -2
- data/spec/spec_helper.rb +14 -3
- metadata +27 -9
@@ -1,8 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "oracle_common"
|
4
|
+
|
3
5
|
module Arel # :nodoc: all
|
4
6
|
module Visitors
|
5
7
|
class Oracle12 < Arel::Visitors::ToSql
|
8
|
+
include OracleCommon
|
9
|
+
|
6
10
|
private
|
7
11
|
def visit_Arel_Nodes_SelectStatement(o, collector)
|
8
12
|
# Oracle does not allow LIMIT clause with select for update
|
@@ -45,7 +49,6 @@ module Arel # :nodoc: all
|
|
45
49
|
def visit_Arel_Nodes_HomogeneousIn(o, collector)
|
46
50
|
in_clause_length = @connection.in_clause_length
|
47
51
|
values = o.casted_values.map { |v| @connection.quote(v) }
|
48
|
-
column_name = quote_table_name(o.table_name) + "." + quote_column_name(o.column_name)
|
49
52
|
operator =
|
50
53
|
if o.type == :in
|
51
54
|
" IN ("
|
@@ -54,7 +57,7 @@ module Arel # :nodoc: all
|
|
54
57
|
end
|
55
58
|
|
56
59
|
if !Array === values || values.length <= in_clause_length
|
57
|
-
|
60
|
+
visit o.left, collector
|
58
61
|
collector << operator
|
59
62
|
|
60
63
|
expr =
|
@@ -76,15 +79,13 @@ module Arel # :nodoc: all
|
|
76
79
|
collector << "("
|
77
80
|
values.each_slice(in_clause_length).each_with_index do |valuez, i|
|
78
81
|
collector << separator unless i == 0
|
79
|
-
|
82
|
+
visit o.left, collector
|
80
83
|
collector << operator
|
81
84
|
collector << valuez.join(",")
|
82
85
|
collector << ")"
|
83
86
|
end
|
84
87
|
collector << ")"
|
85
88
|
end
|
86
|
-
|
87
|
-
collector
|
88
89
|
end
|
89
90
|
|
90
91
|
def visit_Arel_Nodes_UpdateStatement(o, collector)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arel # :nodoc: all
|
4
|
+
module Visitors
|
5
|
+
module OracleCommon
|
6
|
+
private
|
7
|
+
# Oracle can't compare CLOB columns with standard SQL operators for comparison.
|
8
|
+
# We need to replace standard equality for text/binary columns to use DBMS_LOB.COMPARE function.
|
9
|
+
# Fixes ORA-00932: inconsistent datatypes: expected - got CLOB
|
10
|
+
def visit_Arel_Nodes_Equality(o, collector)
|
11
|
+
left = o.left
|
12
|
+
return super unless %i(text binary).include?(cached_column_for(left)&.type)
|
13
|
+
|
14
|
+
# https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lob.htm#i1016668
|
15
|
+
# returns 0 when the comparison succeeds
|
16
|
+
comparator = Arel::Nodes::NamedFunction.new("DBMS_LOB.COMPARE", [left, o.right])
|
17
|
+
collector = visit comparator, collector
|
18
|
+
collector << " = 0"
|
19
|
+
collector
|
20
|
+
end
|
21
|
+
|
22
|
+
def visit_Arel_Nodes_Matches(o, collector)
|
23
|
+
if !o.case_sensitive && o.left && o.right
|
24
|
+
o.left = Arel::Nodes::NamedFunction.new("UPPER", [o.left])
|
25
|
+
o.right = Arel::Nodes::NamedFunction.new("UPPER", [o.right])
|
26
|
+
end
|
27
|
+
|
28
|
+
super o, collector
|
29
|
+
end
|
30
|
+
|
31
|
+
def cached_column_for(attr)
|
32
|
+
return unless Arel::Attributes::Attribute === attr
|
33
|
+
|
34
|
+
table = attr.relation.name
|
35
|
+
return unless schema_cache.columns_hash?(table)
|
36
|
+
|
37
|
+
column = attr.name.to_s
|
38
|
+
schema_cache.columns_hash(table)[column]
|
39
|
+
end
|
40
|
+
|
41
|
+
def schema_cache
|
42
|
+
@connection.schema_cache
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -44,7 +44,7 @@ describe "OracleEnhancedAdapter establish connection" do
|
|
44
44
|
it "should not use JDBC statement caching" do
|
45
45
|
if ORACLE_ENHANCED_CONNECTION == :jdbc
|
46
46
|
ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS)
|
47
|
-
expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to
|
47
|
+
expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to be(false)
|
48
48
|
expect(ActiveRecord::Base.connection.raw_connection.getStatementCacheSize).to eq(-1)
|
49
49
|
end
|
50
50
|
end
|
@@ -52,12 +52,26 @@ describe "OracleEnhancedAdapter establish connection" do
|
|
52
52
|
it "should use JDBC statement caching" do
|
53
53
|
if ORACLE_ENHANCED_CONNECTION == :jdbc
|
54
54
|
ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_statement_cache_size: 100))
|
55
|
-
expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to
|
55
|
+
expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to be(true)
|
56
56
|
expect(ActiveRecord::Base.connection.raw_connection.getStatementCacheSize).to eq(100)
|
57
57
|
# else: don't raise error if OCI connection has parameter "jdbc_statement_cache_size", still ignore it
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
it "should not encrypt JDBC network connection" do
|
62
|
+
if ORACLE_ENHANCED_CONNECTION == :jdbc
|
63
|
+
@conn = ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_connect_properties: { "oracle.net.encryption_client" => "REJECTED" }))
|
64
|
+
expect(@conn.select("SELECT COUNT(*) Records FROM v$Session_Connect_Info WHERE SID=SYS_CONTEXT('USERENV', 'SID') AND Network_Service_Banner LIKE '%Encryption service adapter%'")).to eq([{ "records" => 0 }])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should encrypt JDBC network connection" do
|
69
|
+
if ORACLE_ENHANCED_CONNECTION == :jdbc
|
70
|
+
@conn = ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_connect_properties: { "oracle.net.encryption_client" => "REQUESTED" }))
|
71
|
+
expect(@conn.select("SELECT COUNT(*) Records FROM v$Session_Connect_Info WHERE SID=SYS_CONTEXT('USERENV', 'SID') AND Network_Service_Banner LIKE '%Encryption service adapter%'")).to eq([{ "records" => 1 }])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
61
75
|
it "should connect to database using service_name" do
|
62
76
|
ActiveRecord::Base.establish_connection(SERVICE_NAME_CONNECTION_PARAMS)
|
63
77
|
expect(ActiveRecord::Base.connection).not_to be_nil
|
@@ -227,7 +241,7 @@ describe "OracleEnhancedConnection" do
|
|
227
241
|
end
|
228
242
|
|
229
243
|
after(:all) do
|
230
|
-
Object.send(:remove_const, "Post")
|
244
|
+
Object.send(:remove_const, "Post") if defined?(Post)
|
231
245
|
ActiveRecord::Base.clear_cache!
|
232
246
|
end
|
233
247
|
|
@@ -392,7 +406,7 @@ describe "OracleEnhancedConnection" do
|
|
392
406
|
@conn.exec "DROP TABLE test_employees" rescue nil
|
393
407
|
end
|
394
408
|
|
395
|
-
it "should execute prepared statement with decimal bind parameter
|
409
|
+
it "should execute prepared statement with decimal bind parameter" do
|
396
410
|
cursor = @conn.prepare("INSERT INTO test_employees VALUES(:1)")
|
397
411
|
type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "NUMBER", type: :decimal, limit: 10, precision: nil, scale: 2)
|
398
412
|
column = ActiveRecord::ConnectionAdapters::OracleEnhanced::Column.new("age", nil, type_metadata, false, comment: nil)
|
@@ -414,7 +428,7 @@ describe "OracleEnhancedConnection" do
|
|
414
428
|
|
415
429
|
before(:all) do
|
416
430
|
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
417
|
-
@conn = ActiveRecord::Base.connection.
|
431
|
+
@conn = ActiveRecord::Base.connection.send(:_connection)
|
418
432
|
@sys_conn = ActiveRecord::ConnectionAdapters::OracleEnhanced::Connection.create(SYS_CONNECTION_PARAMS)
|
419
433
|
schema_define do
|
420
434
|
create_table :posts, force: true
|
@@ -447,6 +461,11 @@ describe "OracleEnhancedConnection" do
|
|
447
461
|
expect(@conn.exec("SELECT * FROM dual")).not_to be_nil
|
448
462
|
end
|
449
463
|
|
464
|
+
it "should reconnect and execute SQL statement if connection is lost and allow_retry is passed" do
|
465
|
+
kill_current_session
|
466
|
+
expect(@conn.exec("SELECT * FROM dual", allow_retry: true)).not_to be_nil
|
467
|
+
end
|
468
|
+
|
450
469
|
it "should not reconnect and execute SQL statement if connection is lost and auto retry is disabled" do
|
451
470
|
# @conn.auto_retry = false
|
452
471
|
ActiveRecord::Base.connection.auto_retry = false
|
@@ -16,6 +16,7 @@ describe "Oracle Enhanced adapter database tasks" do
|
|
16
16
|
ActiveRecord::Tasks::DatabaseTasks.create(new_user_config)
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
19
20
|
it "creates user" do
|
20
21
|
query = "SELECT COUNT(*) FROM dba_users WHERE UPPER(username) = '#{new_user_config[:username].upcase}'"
|
21
22
|
expect(ActiveRecord::Base.connection.select_value(query)).to eq(1)
|
@@ -62,6 +63,7 @@ describe "Oracle Enhanced adapter database tasks" do
|
|
62
63
|
|
63
64
|
describe "drop" do
|
64
65
|
before { ActiveRecord::Tasks::DatabaseTasks.drop(config) }
|
66
|
+
|
65
67
|
it "drops all tables" do
|
66
68
|
expect(ActiveRecord::Base.connection.table_exists?(:test_posts)).to be_falsey
|
67
69
|
end
|
@@ -69,6 +71,7 @@ describe "Oracle Enhanced adapter database tasks" do
|
|
69
71
|
|
70
72
|
describe "purge" do
|
71
73
|
before { ActiveRecord::Tasks::DatabaseTasks.purge(config) }
|
74
|
+
|
72
75
|
it "drops all tables" do
|
73
76
|
expect(ActiveRecord::Base.connection.table_exists?(:test_posts)).to be_falsey
|
74
77
|
expect(ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM RECYCLEBIN")).to eq(0)
|
@@ -78,12 +81,13 @@ describe "Oracle Enhanced adapter database tasks" do
|
|
78
81
|
describe "structure" do
|
79
82
|
let(:temp_file) { Tempfile.create(["oracle_enhanced", ".sql"]).path }
|
80
83
|
before do
|
81
|
-
ActiveRecord::
|
84
|
+
ActiveRecord::Base.connection.schema_migration.create_table
|
82
85
|
ActiveRecord::Base.connection.execute "INSERT INTO schema_migrations (version) VALUES ('20150101010000')"
|
83
86
|
end
|
84
87
|
|
85
88
|
describe "structure_dump" do
|
86
89
|
before { ActiveRecord::Tasks::DatabaseTasks.structure_dump(config, temp_file) }
|
90
|
+
|
87
91
|
it "dumps the database structure to a file without the schema information" do
|
88
92
|
contents = File.read(temp_file)
|
89
93
|
expect(contents).to include('CREATE TABLE "TEST_POSTS"')
|
@@ -97,6 +101,7 @@ describe "Oracle Enhanced adapter database tasks" do
|
|
97
101
|
ActiveRecord::Tasks::DatabaseTasks.drop(config)
|
98
102
|
ActiveRecord::Tasks::DatabaseTasks.structure_load(config, temp_file)
|
99
103
|
end
|
104
|
+
|
100
105
|
it "loads the database structure from a file" do
|
101
106
|
expect(ActiveRecord::Base.connection.table_exists?(:test_posts)).to be_truthy
|
102
107
|
end
|
@@ -104,7 +109,7 @@ describe "Oracle Enhanced adapter database tasks" do
|
|
104
109
|
|
105
110
|
after do
|
106
111
|
File.unlink(temp_file)
|
107
|
-
ActiveRecord::
|
112
|
+
ActiveRecord::Base.connection.schema_migration.drop_table
|
108
113
|
end
|
109
114
|
end
|
110
115
|
|
@@ -47,7 +47,7 @@ describe "OracleEnhancedAdapter logging dbms_output from plsql" do
|
|
47
47
|
expect(@logger.output(:debug)).not_to match(/^DBMS_OUTPUT/)
|
48
48
|
end
|
49
49
|
|
50
|
-
it "should log dbms output lines to the rails log" do
|
50
|
+
it "should log dbms output longer lines to the rails log" do
|
51
51
|
@conn.enable_dbms_output
|
52
52
|
|
53
53
|
expect(@conn.select_all("select more_than_five_characters_long('hi there') is_it_long from dual").to_a).to eq([{ "is_it_long" => 1 }])
|
@@ -57,7 +57,7 @@ describe "OracleEnhancedAdapter logging dbms_output from plsql" do
|
|
57
57
|
expect(@logger.output(:debug)).to match(/^DBMS_OUTPUT: about to return: 1$/)
|
58
58
|
end
|
59
59
|
|
60
|
-
it "should log dbms output lines to the rails log" do
|
60
|
+
it "should log dbms output shorter lines to the rails log" do
|
61
61
|
@conn.enable_dbms_output
|
62
62
|
|
63
63
|
expect(@conn.select_all("select more_than_five_characters_long('short') is_it_long from dual").to_a).to eq([{ "is_it_long" => 0 }])
|
@@ -127,6 +127,7 @@ describe "OracleEnhancedAdapter schema dump" do
|
|
127
127
|
remove_foreign_key :test_comments, name: "comments_posts_baz_fooz_fk" rescue nil
|
128
128
|
end
|
129
129
|
end
|
130
|
+
|
130
131
|
after(:all) do
|
131
132
|
schema_define do
|
132
133
|
drop_table :test_comments, if_exists: true
|
@@ -383,6 +384,7 @@ describe "OracleEnhancedAdapter schema dump" do
|
|
383
384
|
end
|
384
385
|
end
|
385
386
|
end
|
387
|
+
|
386
388
|
after(:all) do
|
387
389
|
if @oracle11g_or_higher
|
388
390
|
schema_define do
|
@@ -390,6 +392,7 @@ describe "OracleEnhancedAdapter schema dump" do
|
|
390
392
|
end
|
391
393
|
end
|
392
394
|
end
|
395
|
+
|
393
396
|
it "should dump correctly" do
|
394
397
|
output = dump_table_schema "test_names"
|
395
398
|
expect(output).not_to match(/t\.index .+FIRST_NAME.+$/)
|
@@ -550,6 +550,7 @@ end
|
|
550
550
|
class ::TestPost < ActiveRecord::Base
|
551
551
|
end
|
552
552
|
end
|
553
|
+
|
553
554
|
it "should use default tablespace for clobs" do
|
554
555
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = DATABASE_NON_DEFAULT_TABLESPACE
|
555
556
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = nil
|
@@ -880,7 +881,7 @@ end
|
|
880
881
|
expect(TestPost.columns_hash["a" * 128]).not_to be_nil
|
881
882
|
end
|
882
883
|
|
883
|
-
it "should add lob column with non_default tablespace" do
|
884
|
+
it "should add text type lob column with non_default tablespace" do
|
884
885
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = DATABASE_NON_DEFAULT_TABLESPACE
|
885
886
|
schema_define do
|
886
887
|
add_column :test_posts, :body, :text
|
@@ -888,7 +889,7 @@ end
|
|
888
889
|
expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_lobs WHERE table_name='TEST_POSTS' and column_name = 'BODY'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE)
|
889
890
|
end
|
890
891
|
|
891
|
-
it "should add lob column with non_default tablespace" do
|
892
|
+
it "should add ntext type lob column with non_default tablespace" do
|
892
893
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:nclob] = DATABASE_NON_DEFAULT_TABLESPACE
|
893
894
|
schema_define do
|
894
895
|
add_column :test_posts, :body, :ntext
|
@@ -995,12 +996,12 @@ end
|
|
995
996
|
|
996
997
|
it "should include virtual columns and not try to update them" do
|
997
998
|
tf = TestFraction.columns.detect { |c| c.virtual? }
|
998
|
-
expect(tf).not_to
|
999
|
+
expect(tf).not_to be_nil
|
999
1000
|
expect(tf.name).to eq("percent")
|
1000
1001
|
expect(tf.virtual?).to be true
|
1001
1002
|
expect do
|
1002
1003
|
tf = TestFraction.new(numerator: 20, denominator: 100)
|
1003
|
-
expect(tf.percent).to
|
1004
|
+
expect(tf.percent).to be_nil # not whatever is in DATA_DEFAULT column
|
1004
1005
|
tf.save!
|
1005
1006
|
tf.reload
|
1006
1007
|
end.not_to raise_error
|
@@ -1013,11 +1014,11 @@ end
|
|
1013
1014
|
end
|
1014
1015
|
TestFraction.reset_column_information
|
1015
1016
|
tf = TestFraction.columns.detect { |c| c.name == "rem" }
|
1016
|
-
expect(tf).not_to
|
1017
|
+
expect(tf).not_to be_nil
|
1017
1018
|
expect(tf.virtual?).to be true
|
1018
1019
|
expect do
|
1019
1020
|
tf = TestFraction.new(numerator: 7, denominator: 5)
|
1020
|
-
expect(tf.rem).to
|
1021
|
+
expect(tf.rem).to be_nil
|
1021
1022
|
tf.save!
|
1022
1023
|
tf.reload
|
1023
1024
|
end.not_to raise_error
|
@@ -1030,13 +1031,13 @@ end
|
|
1030
1031
|
end
|
1031
1032
|
TestFraction.reset_column_information
|
1032
1033
|
tf = TestFraction.columns.detect { |c| c.name == "expression" }
|
1033
|
-
expect(tf).not_to
|
1034
|
+
expect(tf).not_to be_nil
|
1034
1035
|
expect(tf.virtual?).to be true
|
1035
1036
|
expect(tf.type).to be :string
|
1036
1037
|
expect(tf.limit).to be 100
|
1037
1038
|
expect do
|
1038
1039
|
tf = TestFraction.new(numerator: 7, denominator: 5)
|
1039
|
-
expect(tf.expression).to
|
1040
|
+
expect(tf.expression).to be_nil
|
1040
1041
|
tf.save!
|
1041
1042
|
tf.reload
|
1042
1043
|
end.not_to raise_error
|
@@ -1050,14 +1051,14 @@ end
|
|
1050
1051
|
end
|
1051
1052
|
TestFraction.reset_column_information
|
1052
1053
|
tf = TestFraction.columns.detect { |c| c.name == "percent" }
|
1053
|
-
expect(tf).not_to
|
1054
|
+
expect(tf).not_to be_nil
|
1054
1055
|
expect(tf.virtual?).to be true
|
1055
1056
|
expect(tf.type).to be :decimal
|
1056
1057
|
expect(tf.precision).to be 15
|
1057
1058
|
expect(tf.scale).to be 2
|
1058
1059
|
expect do
|
1059
1060
|
tf = TestFraction.new(numerator: 11, denominator: 17)
|
1060
|
-
expect(tf.percent).to
|
1061
|
+
expect(tf.percent).to be_nil
|
1061
1062
|
tf.save!
|
1062
1063
|
tf.reload
|
1063
1064
|
end.not_to raise_error
|
@@ -1070,14 +1071,14 @@ end
|
|
1070
1071
|
end
|
1071
1072
|
TestFraction.reset_column_information
|
1072
1073
|
tf = TestFraction.columns.detect { |c| c.name == "percent" }
|
1073
|
-
expect(tf).not_to
|
1074
|
+
expect(tf).not_to be_nil
|
1074
1075
|
expect(tf.virtual?).to be true
|
1075
1076
|
expect(tf.type).to be :decimal
|
1076
1077
|
expect(tf.precision).to be 12
|
1077
1078
|
expect(tf.scale).to be 5
|
1078
1079
|
expect do
|
1079
1080
|
tf = TestFraction.new(numerator: 11, denominator: 17)
|
1080
|
-
expect(tf.percent).to
|
1081
|
+
expect(tf.percent).to be_nil
|
1081
1082
|
tf.save!
|
1082
1083
|
tf.reload
|
1083
1084
|
end.not_to raise_error
|
@@ -1157,6 +1158,7 @@ end
|
|
1157
1158
|
@conn.drop_table :tablespace_tests, if_exists: true
|
1158
1159
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:table)
|
1159
1160
|
end
|
1161
|
+
|
1160
1162
|
it "should use correct tablespace" do
|
1161
1163
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:table] = DATABASE_NON_DEFAULT_TABLESPACE
|
1162
1164
|
@conn.create_table :tablespace_tests do |t|
|
@@ -1171,6 +1173,7 @@ end
|
|
1171
1173
|
@conn.drop_table :tablespace_tests, if_exists: true
|
1172
1174
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces.delete(:table)
|
1173
1175
|
end
|
1176
|
+
|
1174
1177
|
it "should use correct tablespace" do
|
1175
1178
|
@conn.create_table :tablespace_tests, id: false, organization: "INDEX INITRANS 4 COMPRESS 1", tablespace: "bogus" do |t|
|
1176
1179
|
t.integer :id
|
@@ -1206,7 +1209,14 @@ end
|
|
1206
1209
|
schema_define do
|
1207
1210
|
add_index :keyboards, "lower(name)", unique: true, name: :index_keyboards_on_lower_name
|
1208
1211
|
end
|
1209
|
-
expect(@would_execute_sql).not_to
|
1212
|
+
expect(@would_execute_sql).not_to include("ADD CONSTRAINT")
|
1213
|
+
end
|
1214
|
+
|
1215
|
+
it "should add unique constraint only to the index where it was defined" do
|
1216
|
+
schema_define do
|
1217
|
+
add_index :keyboards, ["name"], unique: true, name: :this_index
|
1218
|
+
end
|
1219
|
+
expect(@would_execute_sql.lines.last).to match(/ALTER +TABLE .* ADD CONSTRAINT .* UNIQUE \(.*\) USING INDEX "THIS_INDEX";/)
|
1210
1220
|
end
|
1211
1221
|
end
|
1212
1222
|
|
@@ -1218,7 +1228,7 @@ end
|
|
1218
1228
|
before do
|
1219
1229
|
@conn = ActiveRecord::Base.connection
|
1220
1230
|
|
1221
|
-
ActiveRecord::
|
1231
|
+
ActiveRecord::Base.connection.schema_migration.create_table
|
1222
1232
|
end
|
1223
1233
|
|
1224
1234
|
context "multi insert is supported" do
|
@@ -1246,7 +1256,7 @@ end
|
|
1246
1256
|
end
|
1247
1257
|
|
1248
1258
|
after do
|
1249
|
-
ActiveRecord::
|
1259
|
+
ActiveRecord::Base.connection.schema_migration.drop_table
|
1250
1260
|
end
|
1251
1261
|
end
|
1252
1262
|
end
|
@@ -9,6 +9,7 @@ describe "OracleEnhancedAdapter structure dump" do
|
|
9
9
|
@oracle11g_or_higher = !! @conn.select_value(
|
10
10
|
"select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) >= 11")
|
11
11
|
end
|
12
|
+
|
12
13
|
describe "structure dump" do
|
13
14
|
before(:each) do
|
14
15
|
@conn.create_table :test_posts, force: true do |t|
|
@@ -228,25 +229,13 @@ describe "OracleEnhancedAdapter structure dump" do
|
|
228
229
|
dump = ActiveRecord::Base.connection.structure_dump
|
229
230
|
expect(dump).to match(/#{comment_sql}/)
|
230
231
|
end
|
231
|
-
|
232
|
-
it "should dump table comments" do
|
233
|
-
comment_sql = %Q(COMMENT ON TABLE "TEST_POSTS" IS 'Test posts with ''some'' "quotes"')
|
234
|
-
@conn.execute comment_sql
|
235
|
-
dump = ActiveRecord::Base.connection.structure_dump
|
236
|
-
expect(dump).to match(/#{comment_sql}/)
|
237
|
-
end
|
238
|
-
|
239
|
-
it "should dump column comments" do
|
240
|
-
comment_sql = %Q(COMMENT ON COLUMN "TEST_POSTS"."TITLE" IS 'The title of the post with ''some'' "quotes"')
|
241
|
-
@conn.execute comment_sql
|
242
|
-
dump = ActiveRecord::Base.connection.structure_dump
|
243
|
-
expect(dump).to match(/#{comment_sql}/)
|
244
|
-
end
|
245
232
|
end
|
233
|
+
|
246
234
|
describe "temporary tables" do
|
247
235
|
after(:all) do
|
248
236
|
@conn.drop_table :test_comments, if_exists: true
|
249
237
|
end
|
238
|
+
|
250
239
|
it "should dump correctly" do
|
251
240
|
@conn.create_table :test_comments, temporary: true, id: false do |t|
|
252
241
|
t.integer :post_id
|
@@ -261,26 +250,32 @@ describe "OracleEnhancedAdapter structure dump" do
|
|
261
250
|
before(:each) do
|
262
251
|
@conn.execute sql
|
263
252
|
end
|
253
|
+
|
264
254
|
after(:each) do
|
265
255
|
@conn.execute "drop SEQUENCE \"#{sequence_name}\""
|
266
256
|
end
|
257
|
+
|
267
258
|
subject do
|
268
259
|
ActiveRecord::Base.connection.structure_dump
|
269
260
|
end
|
261
|
+
|
270
262
|
context "default sequence" do
|
271
263
|
let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\"" }
|
272
264
|
it { is_expected.to_not match(%r{CREATE SEQUENCE "#{sequence_name}" MAXVALUE \d+ MINVALUE \d+ NOORDER NOCYCLE}) }
|
273
265
|
end
|
266
|
+
|
274
267
|
context "noorder" do
|
275
268
|
let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" NOORDER" }
|
276
269
|
it { is_expected.to include("NOORDER") }
|
277
270
|
it { is_expected.to_not include(" ORDER") }
|
278
271
|
end
|
272
|
+
|
279
273
|
context "order" do
|
280
274
|
let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" ORDER" }
|
281
275
|
it { is_expected.to include(" ORDER") }
|
282
276
|
it { is_expected.to_not include("NOORDER") }
|
283
277
|
end
|
278
|
+
|
284
279
|
context "min max values" do
|
285
280
|
let(:sql) { "CREATE SEQUENCE \"#{sequence_name}\" MINVALUE 7 MAXVALUE 444" }
|
286
281
|
it { is_expected.to include("MINVALUE 7") }
|
@@ -317,6 +312,7 @@ describe "OracleEnhancedAdapter structure dump" do
|
|
317
312
|
t.string :foo
|
318
313
|
end
|
319
314
|
end
|
315
|
+
|
320
316
|
it "should dump drop sql for just temp tables" do
|
321
317
|
dump = @conn.temp_table_drop
|
322
318
|
expect(dump).to match(/DROP TABLE "TEMP_TBL"/)
|
@@ -338,10 +334,9 @@ describe "OracleEnhancedAdapter structure dump" do
|
|
338
334
|
let(:dump) { ActiveRecord::Base.connection.dump_schema_information }
|
339
335
|
|
340
336
|
before do
|
341
|
-
ActiveRecord::
|
342
|
-
ActiveRecord::SchemaMigration.create_table
|
337
|
+
ActiveRecord::Base.connection.schema_migration.create_table
|
343
338
|
versions.each do |i|
|
344
|
-
ActiveRecord::
|
339
|
+
ActiveRecord::Base.connection.schema_migration.create_version(i)
|
345
340
|
end
|
346
341
|
end
|
347
342
|
|
@@ -381,7 +376,7 @@ describe "OracleEnhancedAdapter structure dump" do
|
|
381
376
|
end
|
382
377
|
|
383
378
|
after do
|
384
|
-
ActiveRecord::
|
379
|
+
ActiveRecord::Base.connection.schema_migration.drop_table
|
385
380
|
end
|
386
381
|
end
|
387
382
|
|
@@ -444,6 +439,7 @@ describe "OracleEnhancedAdapter structure dump" do
|
|
444
439
|
create or replace type full_drop_test_type as table of number
|
445
440
|
SQL
|
446
441
|
end
|
442
|
+
|
447
443
|
after(:each) do
|
448
444
|
@conn.drop_table :full_drop_test
|
449
445
|
@conn.drop_table :full_drop_test_temp
|
@@ -455,6 +451,7 @@ describe "OracleEnhancedAdapter structure dump" do
|
|
455
451
|
@conn.execute "DROP PROCEDURE FULL_DROP_TEST_PROCEDURE" rescue nil
|
456
452
|
@conn.execute "DROP TYPE FULL_DROP_TEST_TYPE" rescue nil
|
457
453
|
end
|
454
|
+
|
458
455
|
it "should contain correct sql" do
|
459
456
|
drop = @conn.full_drop
|
460
457
|
expect(drop).to match(/DROP TABLE "FULL_DROP_TEST" CASCADE CONSTRAINTS/)
|
@@ -83,7 +83,7 @@ describe "OracleEnhancedAdapter" do
|
|
83
83
|
expect(@logger.logged(:debug).last).to match(/select .* from all_constraints/im)
|
84
84
|
end
|
85
85
|
|
86
|
-
it "should get primary key from database at
|
86
|
+
it "should get primary key from database at second time without query" do
|
87
87
|
expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
|
88
88
|
@logger.clear(:debug)
|
89
89
|
expect(TestEmployee.connection.pk_and_sequence_for("test_employees")).to eq(["id", "test_employees_seq"])
|
@@ -129,6 +129,7 @@ describe "OracleEnhancedAdapter" do
|
|
129
129
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[:clob] = "UNUSED"
|
130
130
|
@conn = ActiveRecord::Base.connection
|
131
131
|
end
|
132
|
+
|
132
133
|
after(:all) do
|
133
134
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces = {}
|
134
135
|
end
|
@@ -136,6 +137,7 @@ describe "OracleEnhancedAdapter" do
|
|
136
137
|
after(:each) do
|
137
138
|
@conn.drop_table :foos, if_exists: true
|
138
139
|
end
|
140
|
+
|
139
141
|
it "should create ok" do
|
140
142
|
@conn.create_table :foos, temporary: true, id: false do |t|
|
141
143
|
t.integer :id
|
@@ -441,7 +443,7 @@ describe "OracleEnhancedAdapter" do
|
|
441
443
|
end
|
442
444
|
end
|
443
445
|
class ::TestSerializedColumn < ActiveRecord::Base
|
444
|
-
serialize :serialized, Array
|
446
|
+
serialize :serialized, type: Array
|
445
447
|
end
|
446
448
|
end
|
447
449
|
|
@@ -470,12 +472,12 @@ describe "OracleEnhancedAdapter" do
|
|
470
472
|
serialized_column.serialized << new_value
|
471
473
|
expect(serialized_column.serialized).to eq([new_value])
|
472
474
|
serialized_column.save
|
473
|
-
expect(serialized_column.save!).to
|
475
|
+
expect(serialized_column.save!).to be(true)
|
474
476
|
|
475
477
|
serialized_column.reload
|
476
478
|
expect(serialized_column.serialized).to eq([new_value])
|
477
479
|
serialized_column.serialized = []
|
478
|
-
expect(serialized_column.save!).to
|
480
|
+
expect(serialized_column.save!).to be(true)
|
479
481
|
end
|
480
482
|
end
|
481
483
|
|
@@ -514,7 +516,7 @@ describe "OracleEnhancedAdapter" do
|
|
514
516
|
binary_column_object = TestBinaryColumn.new
|
515
517
|
binary_column_object.attachment = binary_value
|
516
518
|
|
517
|
-
expect(binary_column_object.save!).to
|
519
|
+
expect(binary_column_object.save!).to be(true)
|
518
520
|
end
|
519
521
|
end
|
520
522
|
|
@@ -622,8 +624,8 @@ describe "OracleEnhancedAdapter" do
|
|
622
624
|
end
|
623
625
|
|
624
626
|
it "should test table existence" do
|
625
|
-
expect(@conn.table_exists?("TEST_POSTS")).to
|
626
|
-
expect(@conn.table_exists?("NOT_EXISTING")).to
|
627
|
+
expect(@conn.table_exists?("TEST_POSTS")).to be true
|
628
|
+
expect(@conn.table_exists?("NOT_EXISTING")).to be false
|
627
629
|
end
|
628
630
|
|
629
631
|
it "should return array from indexes with bind usage" do
|
@@ -648,13 +650,13 @@ describe "OracleEnhancedAdapter" do
|
|
648
650
|
expect(@logger.logged(:debug).last).to match(/\["table_name", "TEST_POSTS"\]/)
|
649
651
|
end
|
650
652
|
|
651
|
-
it "should not raise missing IN/OUT parameter like issue
|
653
|
+
it "should not raise missing IN/OUT parameter like issue 1678" do
|
652
654
|
# "to_sql" enforces unprepared_statement including dictionary access SQLs
|
653
655
|
expect { User.joins(:group).to_sql }.not_to raise_exception
|
654
656
|
end
|
655
657
|
|
656
658
|
it "should return false from temporary_table? with bind usage" do
|
657
|
-
expect(@conn.temporary_table?("TEST_POSTS")).to
|
659
|
+
expect(@conn.temporary_table?("TEST_POSTS")).to be false
|
658
660
|
expect(@logger.logged(:debug).last).to match(/:table_name/)
|
659
661
|
expect(@logger.logged(:debug).last).to match(/\["table_name", "TEST_POSTS"\]/)
|
660
662
|
end
|
@@ -721,12 +723,14 @@ describe "OracleEnhancedAdapter" do
|
|
721
723
|
end
|
722
724
|
end
|
723
725
|
end
|
726
|
+
|
724
727
|
after(:all) do
|
725
728
|
schema_define do
|
726
729
|
drop_table :table_with_name_thats_just_ok,
|
727
730
|
sequence_name: "suitably_short_seq" rescue nil
|
728
731
|
end
|
729
732
|
end
|
733
|
+
|
730
734
|
it "should create table with custom sequence name" do
|
731
735
|
expect(@conn.select_value("select suitably_short_seq.nextval from dual")).to eq(1)
|
732
736
|
end
|
@@ -767,7 +771,7 @@ describe "OracleEnhancedAdapter" do
|
|
767
771
|
expect(post.explain).to include("| TABLE ACCESS FULL| TEST_POSTS |")
|
768
772
|
end
|
769
773
|
|
770
|
-
it "should explain considers hints with /*+ */
|
774
|
+
it "should explain considers hints with /*+ */" do
|
771
775
|
post = TestPost.optimizer_hints("/*+ FULL (\"TEST_POSTS\") */")
|
772
776
|
post = post.where(id: 1)
|
773
777
|
expect(post.explain).to include("| TABLE ACCESS FULL| TEST_POSTS |")
|
@@ -151,10 +151,10 @@ describe "OracleEnhancedAdapter boolean type detection based on string column ty
|
|
151
151
|
expect(@employee3.test_boolean_before_type_cast).to eq("N")
|
152
152
|
create_employee3(test_boolean: nil)
|
153
153
|
expect(@employee3.test_boolean.class).to eq(NilClass)
|
154
|
-
expect(@employee3.test_boolean_before_type_cast).to
|
154
|
+
expect(@employee3.test_boolean_before_type_cast).to be_nil
|
155
155
|
create_employee3(test_boolean: "")
|
156
156
|
expect(@employee3.test_boolean.class).to eq(NilClass)
|
157
|
-
expect(@employee3.test_boolean_before_type_cast).to
|
157
|
+
expect(@employee3.test_boolean_before_type_cast).to be_nil
|
158
158
|
end
|
159
159
|
|
160
160
|
it "should return string value from VARCHAR2 column with boolean column name but attribute is set to :string" do
|