activerecord-oracle_enhanced-adapter 7.0.3 → 7.1.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +28 -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 +32 -22
- 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 +2 -2
- 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 +22 -22
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +17 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +71 -28
- 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/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 +8 -6
@@ -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
|
@@ -24,6 +24,7 @@ describe "OracleEnhancedAdapter processing CHAR column" do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
after(:each) do
|
27
|
+
TestItem.delete_all
|
27
28
|
Object.send(:remove_const, "TestItem")
|
28
29
|
ActiveRecord::Base.clear_cache!
|
29
30
|
end
|
@@ -40,4 +41,27 @@ describe "OracleEnhancedAdapter processing CHAR column" do
|
|
40
41
|
item_reloaded = TestItem.first
|
41
42
|
expect(item_reloaded.padded).to eq(str)
|
42
43
|
end
|
44
|
+
|
45
|
+
it "should support case sensitive matching" do
|
46
|
+
TestItem.create!(
|
47
|
+
padded: "First",
|
48
|
+
)
|
49
|
+
TestItem.create!(
|
50
|
+
padded: "first",
|
51
|
+
)
|
52
|
+
|
53
|
+
expect(TestItem.where(TestItem.arel_table[:padded].matches("first%", "\\", true))).to have_attributes(count: 1)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should support case insensitive matching" do
|
57
|
+
TestItem.create!(
|
58
|
+
padded: "First",
|
59
|
+
)
|
60
|
+
TestItem.create!(
|
61
|
+
padded: "first",
|
62
|
+
)
|
63
|
+
|
64
|
+
expect(TestItem.where(TestItem.arel_table[:padded].matches("first%", "\\", false))).to have_attributes(count: 2)
|
65
|
+
expect(TestItem.where(TestItem.arel_table[:padded].matches("first%"))).to have_attributes(count: 2)
|
66
|
+
end
|
43
67
|
end
|
@@ -113,7 +113,7 @@ describe "OracleEnhancedAdapter dirty object tracking" do
|
|
113
113
|
|
114
114
|
it "should not update unchanged CLOBs" do
|
115
115
|
@conn = nil
|
116
|
-
@
|
116
|
+
@raw_connection = nil
|
117
117
|
@employee = TestEmployee.create!(
|
118
118
|
comments: "initial"
|
119
119
|
)
|
@@ -121,10 +121,12 @@ describe "OracleEnhancedAdapter dirty object tracking" do
|
|
121
121
|
@employee.reload
|
122
122
|
expect(@employee.comments).to eq("initial")
|
123
123
|
|
124
|
-
oci_conn = @conn.instance_variable_get("@
|
124
|
+
oci_conn = @conn.instance_variable_get("@raw_connection")
|
125
125
|
class << oci_conn
|
126
126
|
def write_lob(lob, value, is_binary = false); raise "don't do this'"; end
|
127
127
|
end
|
128
|
+
@employee.comments = +"initial"
|
129
|
+
expect(@employee.comments_changed?).to be false
|
128
130
|
expect { @employee.save! }.not_to raise_error
|
129
131
|
class << oci_conn
|
130
132
|
remove_method :write_lob
|