activerecord-oracle_enhanced-adapter 1.5.6 → 1.6.9
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/.travis/oracle/download.sh +14 -0
- data/.travis/oracle/install.sh +31 -0
- data/.travis/setup_accounts.sh +9 -0
- data/.travis.yml +39 -0
- data/Gemfile +8 -8
- data/History.md +189 -0
- data/README.md +388 -178
- data/RUNNING_TESTS.md +11 -6
- data/VERSION +1 -1
- data/activerecord-oracle_enhanced-adapter.gemspec +29 -26
- data/lib/active_record/connection_adapters/{oracle_enhanced_column.rb → oracle_enhanced/column.rb} +14 -63
- data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +66 -0
- data/lib/active_record/connection_adapters/{oracle_enhanced_connection.rb → oracle_enhanced/connection.rb} +2 -2
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +347 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +260 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/dirty.rb +40 -0
- data/lib/active_record/connection_adapters/{oracle_enhanced_jdbc_connection.rb → oracle_enhanced/jdbc_connection.rb} +13 -4
- data/lib/active_record/connection_adapters/{oracle_enhanced_oci_connection.rb → oracle_enhanced/oci_connection.rb} +11 -5
- data/lib/active_record/connection_adapters/{oracle_enhanced_procedures.rb → oracle_enhanced/procedures.rb} +1 -1
- data/lib/active_record/connection_adapters/{oracle_enhanced_schema_creation.rb → oracle_enhanced/schema_creation.rb} +34 -35
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/{oracle_enhanced_schema_dumper.rb → oracle_enhanced/schema_dumper.rb} +14 -37
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +562 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +65 -0
- data/lib/active_record/connection_adapters/{oracle_enhanced_structure_dump.rb → oracle_enhanced/structure_dump.rb} +63 -14
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +171 -73
- data/lib/active_record/oracle_enhanced/type/integer.rb +13 -0
- data/lib/active_record/oracle_enhanced/type/raw.rb +13 -0
- data/lib/active_record/oracle_enhanced/type/timestamp.rb +11 -0
- data/lib/activerecord-oracle_enhanced-adapter.rb +1 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +127 -49
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +46 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +11 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +3 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +151 -78
- data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +4 -4
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +10 -16
- data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +1 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +5 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +65 -181
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +114 -11
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +17 -1
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +31 -12
- data/spec/support/alter_system_user_password.sql +2 -0
- data/spec/support/create_oracle_enhanced_users.sql +31 -0
- metadata +37 -27
- data/lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb +0 -77
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -350
- data/lib/active_record/connection_adapters/oracle_enhanced_database_statements.rb +0 -262
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -45
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -197
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -450
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -258
- data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
- /data/lib/active_record/connection_adapters/{oracle_enhanced_cpk.rb → oracle_enhanced/cpk.rb} +0 -0
- /data/lib/active_record/connection_adapters/{oracle_enhanced_database_tasks.rb → oracle_enhanced/database_tasks.rb} +0 -0
@@ -25,7 +25,9 @@ module ActiveRecord
|
|
25
25
|
def initialize(config)
|
26
26
|
@raw_connection = OCI8EnhancedAutoRecover.new(config, OracleEnhancedOCIFactory)
|
27
27
|
# default schema owner
|
28
|
-
@owner = config[:
|
28
|
+
@owner = config[:schema]
|
29
|
+
@owner ||= config[:username]
|
30
|
+
@owner = @owner.to_s.upcase
|
29
31
|
end
|
30
32
|
|
31
33
|
def raw_oci_connection
|
@@ -237,12 +239,12 @@ module ActiveRecord
|
|
237
239
|
|
238
240
|
def typecast_result_value(value, get_lob_value)
|
239
241
|
case value
|
240
|
-
when
|
242
|
+
when Integer
|
241
243
|
value
|
242
244
|
when String
|
243
245
|
value
|
244
246
|
when Float, BigDecimal
|
245
|
-
# return
|
247
|
+
# return Integer if value is integer (to avoid issues with _before_type_cast values for id attributes)
|
246
248
|
value == (v_to_i = value.to_i) ? v_to_i : value
|
247
249
|
when OraNumber
|
248
250
|
# change OraNumber value (returned in early versions of ruby-oci8 2.0.x) to BigDecimal
|
@@ -306,6 +308,7 @@ module ActiveRecord
|
|
306
308
|
username = config[:username] && config[:username].to_s
|
307
309
|
password = config[:password] && config[:password].to_s
|
308
310
|
database = config[:database] && config[:database].to_s
|
311
|
+
schema = config[:schema] && config[:schema].to_s
|
309
312
|
host, port = config[:host], config[:port]
|
310
313
|
privilege = config[:privilege] && config[:privilege].to_sym
|
311
314
|
async = config[:allow_concurrency]
|
@@ -314,8 +317,11 @@ module ActiveRecord
|
|
314
317
|
# get session time_zone from configuration or from TZ environment variable
|
315
318
|
time_zone = config[:time_zone] || ENV['TZ']
|
316
319
|
|
320
|
+
# using a connection string via DATABASE_URL
|
321
|
+
connection_string = if host == 'connection-string'
|
322
|
+
database
|
317
323
|
# connection using host, port and database name
|
318
|
-
|
324
|
+
elsif host || port
|
319
325
|
host ||= 'localhost'
|
320
326
|
host = "[#{host}]" if host =~ /^[^\[].*:/ # IPv6
|
321
327
|
port ||= 1521
|
@@ -326,13 +332,13 @@ module ActiveRecord
|
|
326
332
|
else
|
327
333
|
database
|
328
334
|
end
|
329
|
-
|
330
335
|
conn = OCI8.new username, password, connection_string, privilege
|
331
336
|
conn.autocommit = true
|
332
337
|
conn.non_blocking = true if async
|
333
338
|
conn.prefetch_rows = prefetch_rows
|
334
339
|
conn.exec "alter session set cursor_sharing = #{cursor_sharing}" rescue nil
|
335
340
|
conn.exec "alter session set time_zone = '#{time_zone}'" unless time_zone.blank?
|
341
|
+
conn.exec "alter session set current_schema = #{schema}" unless schema.blank?
|
336
342
|
|
337
343
|
# Initialize NLS parameters
|
338
344
|
OracleEnhancedAdapter::DEFAULT_NLS_PARAMETERS.each do |key, default_value|
|
@@ -152,7 +152,7 @@ module ActiveRecord #:nodoc:
|
|
152
152
|
if partial_writes?
|
153
153
|
# Serialized attributes should always be written in case they've been
|
154
154
|
# changed in place.
|
155
|
-
update_using_custom_method(changed | (attributes.keys & self.class.
|
155
|
+
update_using_custom_method(changed | (attributes.keys & self.class.columns.select {|column| column.cast_type.is_a?(Type::Serialized)}))
|
156
156
|
else
|
157
157
|
update_using_custom_method(attribute_names)
|
158
158
|
end
|
@@ -1,53 +1,47 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
|
-
|
3
|
+
module OracleEnhanced
|
4
4
|
class SchemaCreation < AbstractAdapter::SchemaCreation
|
5
5
|
private
|
6
6
|
|
7
7
|
def visit_ColumnDefinition(o)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
case
|
9
|
+
when o.type.to_sym == :virtual
|
10
|
+
sql_type = type_to_sql(o.default[:type], o.limit, o.precision, o.scale) if o.default[:type]
|
11
|
+
return "#{quote_column_name(o.name)} #{sql_type} AS (#{o.default[:as]})"
|
12
|
+
when [:blob, :clob].include?(sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale).downcase.to_sym)
|
13
|
+
if (tablespace = default_tablespace_for(sql_type))
|
14
|
+
@lob_tablespaces ||= {}
|
15
|
+
@lob_tablespaces[o.name] = tablespace
|
16
|
+
end
|
13
17
|
end
|
18
|
+
super
|
14
19
|
end
|
15
20
|
|
16
21
|
def visit_TableDefinition(o)
|
17
|
-
tablespace = tablespace_for(:table, o.options[:tablespace])
|
18
22
|
create_sql = "CREATE#{' GLOBAL TEMPORARY' if o.temporary} TABLE "
|
19
23
|
create_sql << "#{quote_table_name(o.name)} ("
|
20
24
|
create_sql << o.columns.map { |c| accept c }.join(', ')
|
21
25
|
create_sql << ")"
|
26
|
+
|
22
27
|
unless o.temporary
|
28
|
+
@lob_tablespaces.each do |lob_column, tablespace|
|
29
|
+
create_sql << " LOB (#{quote_column_name(lob_column)}) STORE AS (TABLESPACE #{tablespace}) \n"
|
30
|
+
end if defined?(@lob_tablespaces)
|
23
31
|
create_sql << " ORGANIZATION #{o.options[:organization]}" if o.options[:organization]
|
24
|
-
|
32
|
+
if (tablespace = o.options[:tablespace] || default_tablespace_for(:table))
|
33
|
+
create_sql << " TABLESPACE #{tablespace}"
|
34
|
+
end
|
25
35
|
end
|
26
36
|
create_sql << " #{o.options[:options]}"
|
27
37
|
create_sql
|
28
38
|
end
|
29
39
|
|
30
|
-
def tablespace_for(obj_type, tablespace_option, table_name=nil, column_name=nil)
|
31
|
-
tablespace_sql = ''
|
32
|
-
if tablespace = (tablespace_option || default_tablespace_for(obj_type))
|
33
|
-
tablespace_sql << if [:blob, :clob].include?(obj_type.to_sym)
|
34
|
-
" LOB (#{quote_column_name(column_name)}) STORE AS #{column_name.to_s[0..10]}_#{table_name.to_s[0..14]}_ls (TABLESPACE #{tablespace})"
|
35
|
-
else
|
36
|
-
" TABLESPACE #{tablespace}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
tablespace_sql
|
40
|
-
end
|
41
|
-
|
42
40
|
def default_tablespace_for(type)
|
43
41
|
(ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[type] ||
|
44
42
|
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces[native_database_types[type][:name]]) rescue nil
|
45
43
|
end
|
46
44
|
|
47
|
-
def foreign_key_definition(to_table, options = {})
|
48
|
-
@conn.foreign_key_definition(to_table, options)
|
49
|
-
end
|
50
|
-
|
51
45
|
def add_column_options!(sql, options)
|
52
46
|
type = options[:type] || ((column = options[:column]) && column.type)
|
53
47
|
type = type && type.to_sym
|
@@ -56,8 +50,7 @@ module ActiveRecord
|
|
56
50
|
if type == :text
|
57
51
|
sql << " DEFAULT #{@conn.quote(options[:default])}"
|
58
52
|
else
|
59
|
-
|
60
|
-
sql << " DEFAULT #{@conn.quote(options[:default], options[:column])}"
|
53
|
+
sql << " DEFAULT #{quote_value(options[:default], options[:column])}"
|
61
54
|
end
|
62
55
|
end
|
63
56
|
# must explicitly add NULL or NOT NULL to allow change_column to work on migrations
|
@@ -72,18 +65,24 @@ module ActiveRecord
|
|
72
65
|
end
|
73
66
|
end
|
74
67
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
68
|
+
def action_sql(action, dependency)
|
69
|
+
if action == 'UPDATE'
|
70
|
+
raise ArgumentError, <<-MSG.strip_heredoc
|
71
|
+
'#{action}' is not supported by Oracle
|
72
|
+
MSG
|
73
|
+
end
|
74
|
+
case dependency
|
75
|
+
when :nullify then "ON #{action} SET NULL"
|
76
|
+
when :cascade then "ON #{action} CASCADE"
|
77
|
+
else
|
78
|
+
raise ArgumentError, <<-MSG.strip_heredoc
|
79
|
+
'#{dependency}' is not supported for #{action}
|
80
|
+
Supported values are: :nullify, :cascade
|
81
|
+
MSG
|
82
|
+
end
|
79
83
|
end
|
80
84
|
|
81
85
|
end
|
82
|
-
|
83
|
-
def schema_creation
|
84
|
-
SchemaCreation.new self
|
85
|
-
end
|
86
|
-
|
87
86
|
end
|
88
87
|
end
|
89
88
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
#TODO: Overriding `aliased_types` cause another database adapter behavior changes
|
4
|
+
#It should be addressed by supporting `create_table_definition`
|
5
|
+
class TableDefinition
|
6
|
+
private
|
7
|
+
def aliased_types(name, fallback)
|
8
|
+
fallback
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module OracleEnhanced
|
13
|
+
|
14
|
+
class ForeignKeyDefinition < ActiveRecord::ConnectionAdapters::ForeignKeyDefinition
|
15
|
+
def name
|
16
|
+
if options[:name].length > OracleEnhancedAdapter::IDENTIFIER_MAX_LENGTH
|
17
|
+
ActiveSupport::Deprecation.warn "Foreign key name #{options[:name]} is too long. It will not get shorten in later version of Oracle enhanced adapter"
|
18
|
+
'c'+Digest::SHA1.hexdigest(options[:name])[0,OracleEnhancedAdapter::IDENTIFIER_MAX_LENGTH-1]
|
19
|
+
else
|
20
|
+
options[:name]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class SynonymDefinition < Struct.new(:name, :table_owner, :table_name, :db_link) #:nodoc:
|
26
|
+
end
|
27
|
+
|
28
|
+
class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition
|
29
|
+
attr_accessor :table, :name, :unique, :type, :parameters, :statement_parameters, :tablespace, :columns
|
30
|
+
|
31
|
+
def initialize(table, name, unique, type, parameters, statement_parameters, tablespace, columns)
|
32
|
+
@table = table
|
33
|
+
@name = name
|
34
|
+
@unique = unique
|
35
|
+
@type = type
|
36
|
+
@parameters = parameters
|
37
|
+
@statement_parameters = statement_parameters
|
38
|
+
@tablespace = tablespace
|
39
|
+
@columns = columns
|
40
|
+
super(table, name, unique, columns, nil, nil, nil, nil)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
45
|
+
|
46
|
+
def raw(name, options={})
|
47
|
+
column(name, :raw, options)
|
48
|
+
end
|
49
|
+
|
50
|
+
def virtual(* args)
|
51
|
+
options = args.extract_options!
|
52
|
+
column_names = args
|
53
|
+
column_names.each { |name| column(name, :virtual, options) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def column(name, type, options = {})
|
57
|
+
if type == :virtual
|
58
|
+
default = {:type => options[:type]}
|
59
|
+
if options[:as]
|
60
|
+
default[:as] = options[:as]
|
61
|
+
elsif options[:default]
|
62
|
+
warn "[DEPRECATION] virtual column `:default` option is deprecated. Please use `:as` instead."
|
63
|
+
default[:as] = options[:default]
|
64
|
+
else
|
65
|
+
raise "No virtual column definition found."
|
66
|
+
end
|
67
|
+
options[:default] = default
|
68
|
+
end
|
69
|
+
super(name, type, options)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
class AlterTable < ActiveRecord::ConnectionAdapters::AlterTable
|
75
|
+
def add_foreign_key(to_table, options)
|
76
|
+
@foreign_key_adds << OracleEnhanced::ForeignKeyDefinition.new(name, to_table, options)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
81
|
+
def foreign_key(to_table, options = {})
|
82
|
+
ActiveSupport::Deprecation.warn "`foreign_key` option will be deprecated. Please use `references` option"
|
83
|
+
to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
|
84
|
+
@base.add_foreign_key(@name, to_table, options)
|
85
|
+
end
|
86
|
+
|
87
|
+
def remove_foreign_key(options = {})
|
88
|
+
ActiveSupport::Deprecation.warn "`remove_foreign_key` option will be deprecated. Please use `remove_references` option"
|
89
|
+
@base.remove_foreign_key(@name, options)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -7,6 +7,7 @@ module ActiveRecord #:nodoc:
|
|
7
7
|
private
|
8
8
|
alias_method_chain :tables, :oracle_enhanced
|
9
9
|
alias_method_chain :indexes, :oracle_enhanced
|
10
|
+
alias_method_chain :foreign_keys, :oracle_enhanced
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -49,44 +50,15 @@ module ActiveRecord #:nodoc:
|
|
49
50
|
|
50
51
|
def primary_key_trigger(table_name, stream)
|
51
52
|
if @connection.respond_to?(:has_primary_key_trigger?) && @connection.has_primary_key_trigger?(table_name)
|
52
|
-
pk,
|
53
|
+
pk, _pk_seq = @connection.pk_and_sequence_for(table_name)
|
53
54
|
stream.print " add_primary_key_trigger #{table_name.inspect}"
|
54
55
|
stream.print ", primary_key: \"#{pk}\"" if pk != 'id'
|
55
56
|
stream.print "\n\n"
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
59
|
-
def
|
60
|
-
|
61
|
-
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
62
|
-
statement_parts = [ ('add_foreign_key ' + foreign_key.from_table.inspect) ]
|
63
|
-
statement_parts << foreign_key.to_table.inspect
|
64
|
-
|
65
|
-
if foreign_key.options[:columns].size == 1
|
66
|
-
column = foreign_key.options[:columns].first
|
67
|
-
if column != "#{foreign_key.to_table.singularize}_id"
|
68
|
-
statement_parts << ('column: ' + column.inspect)
|
69
|
-
end
|
70
|
-
|
71
|
-
if foreign_key.options[:references].first != 'id'
|
72
|
-
statement_parts << ('primary_key: ' + foreign_key.options[:references].first.inspect)
|
73
|
-
end
|
74
|
-
else
|
75
|
-
statement_parts << ('columns: ' + foreign_key.options[:columns].inspect)
|
76
|
-
end
|
77
|
-
|
78
|
-
statement_parts << ('name: ' + foreign_key.options[:name].inspect)
|
79
|
-
|
80
|
-
unless foreign_key.options[:dependent].blank?
|
81
|
-
statement_parts << ('dependent: ' + foreign_key.options[:dependent].inspect)
|
82
|
-
end
|
83
|
-
|
84
|
-
' ' + statement_parts.join(', ')
|
85
|
-
end
|
86
|
-
|
87
|
-
stream.puts add_foreign_key_statements.sort.join("\n")
|
88
|
-
stream.puts
|
89
|
-
end
|
60
|
+
def foreign_keys_with_oracle_enhanced(table_name, stream)
|
61
|
+
return foreign_keys_without_oracle_enhanced(table_name, stream)
|
90
62
|
end
|
91
63
|
|
92
64
|
def synonyms(stream)
|
@@ -149,16 +121,21 @@ module ActiveRecord #:nodoc:
|
|
149
121
|
|
150
122
|
# first dump primary key column
|
151
123
|
if @connection.respond_to?(:pk_and_sequence_for)
|
152
|
-
pk,
|
124
|
+
pk, _pk_seq = @connection.pk_and_sequence_for(table)
|
153
125
|
elsif @connection.respond_to?(:primary_key)
|
154
126
|
pk = @connection.primary_key(table)
|
155
127
|
end
|
156
|
-
|
128
|
+
|
157
129
|
tbl.print " create_table #{table.inspect}"
|
158
|
-
|
130
|
+
|
159
131
|
# addition to make temporary option work
|
160
132
|
tbl.print ", temporary: true" if @connection.temporary_table?(table)
|
161
|
-
|
133
|
+
|
134
|
+
table_comments = @connection.table_comment(table)
|
135
|
+
unless table_comments.nil?
|
136
|
+
tbl.print ", comment: #{table_comments.inspect}"
|
137
|
+
end
|
138
|
+
|
162
139
|
if columns.detect { |c| c.name == pk }
|
163
140
|
if pk != 'id'
|
164
141
|
tbl.print %Q(, primary_key: "#{pk}")
|
@@ -166,7 +143,7 @@ module ActiveRecord #:nodoc:
|
|
166
143
|
else
|
167
144
|
tbl.print ", id: false"
|
168
145
|
end
|
169
|
-
tbl.print ", force:
|
146
|
+
tbl.print ", force: :cascade"
|
170
147
|
tbl.puts " do |t|"
|
171
148
|
|
172
149
|
# then dump all non-primary key columns
|