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
@@ -10,7 +10,7 @@ module ActiveRecord #:nodoc:
|
|
10
10
|
"CREATE SEQUENCE \"#{seq}\""
|
11
11
|
end
|
12
12
|
select_values("SELECT table_name FROM all_tables t
|
13
|
-
WHERE owner = SYS_CONTEXT('userenv', '
|
13
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
|
14
14
|
AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
|
15
15
|
AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
|
16
16
|
ORDER BY 1").each do |table_name|
|
@@ -34,6 +34,8 @@ module ActiveRecord #:nodoc:
|
|
34
34
|
structure << ddl
|
35
35
|
structure << structure_dump_indexes(table_name)
|
36
36
|
structure << structure_dump_unique_keys(table_name)
|
37
|
+
structure << structure_dump_table_comments(table_name)
|
38
|
+
structure << structure_dump_column_comments(table_name)
|
37
39
|
end
|
38
40
|
|
39
41
|
join_with_statement_token(structure) << structure_dump_fk_constraints
|
@@ -77,7 +79,7 @@ module ActiveRecord #:nodoc:
|
|
77
79
|
ON a.constraint_name = c.constraint_name
|
78
80
|
WHERE c.table_name = '#{table.upcase}'
|
79
81
|
AND c.constraint_type = 'P'
|
80
|
-
AND c.owner = SYS_CONTEXT('userenv', '
|
82
|
+
AND c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
81
83
|
SQL
|
82
84
|
pks.each do |row|
|
83
85
|
opts[:name] = row['constraint_name']
|
@@ -95,7 +97,7 @@ module ActiveRecord #:nodoc:
|
|
95
97
|
ON a.constraint_name = c.constraint_name
|
96
98
|
WHERE c.table_name = '#{table.upcase}'
|
97
99
|
AND c.constraint_type = 'U'
|
98
|
-
AND c.owner = SYS_CONTEXT('userenv', '
|
100
|
+
AND c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
99
101
|
SQL
|
100
102
|
uks.each do |uk|
|
101
103
|
keys[uk['constraint_name']] ||= []
|
@@ -123,7 +125,7 @@ module ActiveRecord #:nodoc:
|
|
123
125
|
end
|
124
126
|
|
125
127
|
def structure_dump_fk_constraints #:nodoc:
|
126
|
-
fks = select_all("SELECT table_name FROM all_tables WHERE owner = SYS_CONTEXT('userenv', '
|
128
|
+
fks = select_all("SELECT table_name FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1").map do |table|
|
127
129
|
if respond_to?(:foreign_keys) && (foreign_keys = foreign_keys(table["table_name"])).any?
|
128
130
|
foreign_keys.map do |fk|
|
129
131
|
sql = "ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
|
@@ -134,12 +136,59 @@ module ActiveRecord #:nodoc:
|
|
134
136
|
join_with_statement_token(fks)
|
135
137
|
end
|
136
138
|
|
137
|
-
def
|
138
|
-
|
139
|
-
|
140
|
-
|
139
|
+
def structure_dump_table_comments(table_name)
|
140
|
+
comments = []
|
141
|
+
comment = table_comment(table_name)
|
142
|
+
|
143
|
+
unless comment.nil?
|
144
|
+
comments << "COMMENT ON TABLE #{quote_table_name(table_name)} IS '#{quote_string(comment)}'"
|
145
|
+
end
|
146
|
+
|
147
|
+
join_with_statement_token(comments)
|
148
|
+
end
|
149
|
+
|
150
|
+
def structure_dump_column_comments(table_name)
|
151
|
+
comments = []
|
152
|
+
columns = select_values("SELECT column_name FROM user_tab_columns WHERE table_name = '#{table_name}' ORDER BY column_id")
|
153
|
+
|
154
|
+
columns.each do |column|
|
155
|
+
comment = column_comment(table_name, column)
|
156
|
+
unless comment.nil?
|
157
|
+
comments << "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column)} IS '#{quote_string(comment)}'"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
join_with_statement_token(comments)
|
141
162
|
end
|
142
163
|
|
164
|
+
def foreign_key_definition(to_table, options = {}) #:nodoc:
|
165
|
+
columns = Array(options[:column] || options[:columns])
|
166
|
+
|
167
|
+
if columns.size > 1
|
168
|
+
# composite foreign key
|
169
|
+
columns_sql = columns.map {|c| quote_column_name(c)}.join(',')
|
170
|
+
references = options[:references] || columns
|
171
|
+
references_sql = references.map {|c| quote_column_name(c)}.join(',')
|
172
|
+
else
|
173
|
+
columns_sql = quote_column_name(columns.first || "#{to_table.to_s.singularize}_id")
|
174
|
+
references = options[:references] ? options[:references].first : nil
|
175
|
+
references_sql = quote_column_name(options[:primary_key] || references || "id")
|
176
|
+
end
|
177
|
+
|
178
|
+
table_name = to_table
|
179
|
+
|
180
|
+
sql = "FOREIGN KEY (#{columns_sql}) REFERENCES #{quote_table_name(table_name)}(#{references_sql})"
|
181
|
+
|
182
|
+
case options[:dependent]
|
183
|
+
when :nullify
|
184
|
+
sql << " ON DELETE SET NULL"
|
185
|
+
when :delete
|
186
|
+
sql << " ON DELETE CASCADE"
|
187
|
+
end
|
188
|
+
sql
|
189
|
+
end
|
190
|
+
|
191
|
+
|
143
192
|
# Extract all stored procedures, packages, synonyms and views.
|
144
193
|
def structure_dump_db_stored_code #:nodoc:
|
145
194
|
structure = []
|
@@ -147,14 +196,14 @@ module ActiveRecord #:nodoc:
|
|
147
196
|
FROM all_source
|
148
197
|
WHERE type IN ('PROCEDURE', 'PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'TRIGGER', 'TYPE')
|
149
198
|
AND name NOT LIKE 'BIN$%'
|
150
|
-
AND owner = SYS_CONTEXT('userenv', '
|
199
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY type").each do |source|
|
151
200
|
ddl = "CREATE OR REPLACE \n"
|
152
201
|
select_all(%Q{
|
153
202
|
SELECT text
|
154
203
|
FROM all_source
|
155
204
|
WHERE name = '#{source['name']}'
|
156
205
|
AND type = '#{source['type']}'
|
157
|
-
AND owner = SYS_CONTEXT('userenv', '
|
206
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
158
207
|
ORDER BY line
|
159
208
|
}).each do |row|
|
160
209
|
ddl << row['text']
|
@@ -171,7 +220,7 @@ module ActiveRecord #:nodoc:
|
|
171
220
|
# export synonyms
|
172
221
|
select_all("SELECT owner, synonym_name, table_name, table_owner
|
173
222
|
FROM all_synonyms
|
174
|
-
WHERE owner = SYS_CONTEXT('userenv', '
|
223
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ").each do |synonym|
|
175
224
|
structure << "CREATE OR REPLACE #{synonym['owner'] == 'PUBLIC' ? 'PUBLIC' : '' } SYNONYM #{synonym['synonym_name']}
|
176
225
|
FOR #{synonym['table_owner']}.#{synonym['table_name']}"
|
177
226
|
end
|
@@ -184,7 +233,7 @@ module ActiveRecord #:nodoc:
|
|
184
233
|
"DROP SEQUENCE \"#{seq}\""
|
185
234
|
end
|
186
235
|
select_values("SELECT table_name from all_tables t
|
187
|
-
WHERE owner = SYS_CONTEXT('userenv', '
|
236
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
|
188
237
|
AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
|
189
238
|
AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
|
190
239
|
ORDER BY 1").each do |table|
|
@@ -196,7 +245,7 @@ module ActiveRecord #:nodoc:
|
|
196
245
|
def temp_table_drop #:nodoc:
|
197
246
|
join_with_statement_token(select_values(
|
198
247
|
"SELECT table_name FROM all_tables
|
199
|
-
WHERE owner = SYS_CONTEXT('userenv', '
|
248
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N' AND temporary = 'Y' ORDER BY 1").map do |table|
|
200
249
|
"DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
|
201
250
|
end)
|
202
251
|
end
|
@@ -258,7 +307,7 @@ module ActiveRecord #:nodoc:
|
|
258
307
|
AND table_name = '#{table.upcase}'
|
259
308
|
SQL
|
260
309
|
# feature not supported previous to 11g
|
261
|
-
rescue ActiveRecord::StatementInvalid =>
|
310
|
+
rescue ActiveRecord::StatementInvalid => _e
|
262
311
|
[]
|
263
312
|
end
|
264
313
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter::VERSION = File.read(File.expand_path('../../../../../VERSION', __FILE__)).chomp
|
@@ -30,9 +30,13 @@
|
|
30
30
|
# portions Copyright 2005 Graham Jenkins
|
31
31
|
|
32
32
|
require 'active_record/connection_adapters/abstract_adapter'
|
33
|
-
require 'active_record/connection_adapters/
|
33
|
+
require 'active_record/connection_adapters/oracle_enhanced/connection'
|
34
|
+
require 'active_record/connection_adapters/oracle_enhanced/database_statements'
|
35
|
+
require 'active_record/connection_adapters/oracle_enhanced/schema_statements'
|
36
|
+
require 'active_record/connection_adapters/oracle_enhanced/column_dumper'
|
37
|
+
require 'active_record/connection_adapters/oracle_enhanced/context_index'
|
34
38
|
|
35
|
-
require 'active_record/connection_adapters/
|
39
|
+
require 'active_record/connection_adapters/oracle_enhanced/column'
|
36
40
|
|
37
41
|
require 'digest/sha1'
|
38
42
|
|
@@ -131,7 +135,7 @@ module ActiveRecord
|
|
131
135
|
|
132
136
|
def record_changed_lobs
|
133
137
|
@changed_lob_columns = self.class.lob_columns.select do |col|
|
134
|
-
|
138
|
+
self.attribute_changed?(col.name) && !self.class.readonly_attributes.to_a.include?(col.name)
|
135
139
|
end
|
136
140
|
end
|
137
141
|
end
|
@@ -218,6 +222,15 @@ module ActiveRecord
|
|
218
222
|
# * <tt>:nls_time_tz_format</tt>
|
219
223
|
#
|
220
224
|
class OracleEnhancedAdapter < AbstractAdapter
|
225
|
+
# TODO: Use relative
|
226
|
+
include ActiveRecord::ConnectionAdapters::OracleEnhanced::DatabaseStatements
|
227
|
+
include ActiveRecord::ConnectionAdapters::OracleEnhanced::SchemaStatements
|
228
|
+
include ActiveRecord::ConnectionAdapters::OracleEnhanced::ColumnDumper
|
229
|
+
include ActiveRecord::ConnectionAdapters::OracleEnhanced::ContextIndex
|
230
|
+
|
231
|
+
def schema_creation
|
232
|
+
OracleEnhanced::SchemaCreation.new self
|
233
|
+
end
|
221
234
|
|
222
235
|
##
|
223
236
|
# :singleton-method:
|
@@ -270,13 +283,6 @@ module ActiveRecord
|
|
270
283
|
cattr_accessor :emulate_dates_by_column_name
|
271
284
|
self.emulate_dates_by_column_name = false
|
272
285
|
|
273
|
-
##
|
274
|
-
# :singleton-method:
|
275
|
-
# Specify how `NUMBER` datatype columns, without precision and scale, are handled in Rails world.
|
276
|
-
# Default is :decimal and other valid option is :float. Be wary of setting it to other values.
|
277
|
-
cattr_accessor :number_datatype_coercion
|
278
|
-
self.number_datatype_coercion = :decimal
|
279
|
-
|
280
286
|
# Check column name to identify if it is Date (and not Time) column.
|
281
287
|
# Is used if +emulate_dates_by_column_name+ option is set to +true+.
|
282
288
|
# Override this method definition in initializer file if different Date column recognition is needed.
|
@@ -311,7 +317,7 @@ module ActiveRecord
|
|
311
317
|
# Is used if +emulate_integers_by_column_name+ option is set to +true+.
|
312
318
|
# Override this method definition in initializer file if different Integer column recognition is needed.
|
313
319
|
def self.is_integer_column?(name, table_name = nil)
|
314
|
-
|
320
|
+
name =~ /(^|_)id$/i
|
315
321
|
end
|
316
322
|
|
317
323
|
##
|
@@ -326,9 +332,9 @@ module ActiveRecord
|
|
326
332
|
# Check column name to identify if it is boolean (and not String) column.
|
327
333
|
# Is used if +emulate_booleans_from_strings+ option is set to +true+.
|
328
334
|
# Override this method definition in initializer file if different boolean column recognition is needed.
|
329
|
-
def self.is_boolean_column?(name,
|
330
|
-
return true if ["CHAR(1)","VARCHAR2(1)"].include?(
|
331
|
-
|
335
|
+
def self.is_boolean_column?(name, sql_type, table_name = nil)
|
336
|
+
return true if ["CHAR(1)","VARCHAR2(1)"].include?(sql_type)
|
337
|
+
sql_type =~ /^VARCHAR2/ && (name =~ /_flag$/i || name =~ /_yn$/i)
|
332
338
|
end
|
333
339
|
|
334
340
|
# How boolean value should be quoted to String.
|
@@ -383,21 +389,18 @@ module ActiveRecord
|
|
383
389
|
end
|
384
390
|
end
|
385
391
|
|
386
|
-
class BindSubstitution < Arel::Visitors::Oracle #:nodoc:
|
387
|
-
include Arel::Visitors::BindVisitor
|
388
|
-
end
|
389
|
-
|
390
392
|
def initialize(connection, logger, config) #:nodoc:
|
391
393
|
super(connection, logger)
|
392
394
|
@quoted_column_names, @quoted_table_names = {}, {}
|
393
395
|
@config = config
|
394
396
|
@statements = StatementPool.new(connection, config.fetch(:statement_limit) { 250 })
|
395
397
|
@enable_dbms_output = false
|
396
|
-
|
397
|
-
|
398
|
+
@visitor = Arel::Visitors::Oracle.new self
|
399
|
+
|
400
|
+
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
398
401
|
@prepared_statements = true
|
399
402
|
else
|
400
|
-
@
|
403
|
+
@prepared_statements = false
|
401
404
|
end
|
402
405
|
end
|
403
406
|
|
@@ -423,7 +426,13 @@ module ActiveRecord
|
|
423
426
|
true
|
424
427
|
end
|
425
428
|
|
426
|
-
|
429
|
+
def supports_foreign_keys?
|
430
|
+
true
|
431
|
+
end
|
432
|
+
|
433
|
+
def supports_views?
|
434
|
+
true
|
435
|
+
end
|
427
436
|
|
428
437
|
#:stopdoc:
|
429
438
|
DEFAULT_NLS_PARAMETERS = {
|
@@ -448,11 +457,11 @@ module ActiveRecord
|
|
448
457
|
|
449
458
|
#:stopdoc:
|
450
459
|
NATIVE_DATABASE_TYPES = {
|
451
|
-
:primary_key => "NUMBER(
|
460
|
+
:primary_key => "NUMBER(38) NOT NULL PRIMARY KEY",
|
452
461
|
:string => { :name => "VARCHAR2", :limit => 255 },
|
453
462
|
:text => { :name => "CLOB" },
|
454
|
-
:integer => { :name => "NUMBER", :limit =>
|
455
|
-
:float => { :name => "
|
463
|
+
:integer => { :name => "NUMBER", :limit => 38 },
|
464
|
+
:float => { :name => "BINARY_FLOAT" },
|
456
465
|
:decimal => { :name => "DECIMAL" },
|
457
466
|
:datetime => { :name => "DATE" },
|
458
467
|
# changed to native TIMESTAMP type
|
@@ -462,7 +471,8 @@ module ActiveRecord
|
|
462
471
|
:date => { :name => "DATE" },
|
463
472
|
:binary => { :name => "BLOB" },
|
464
473
|
:boolean => { :name => "NUMBER", :limit => 1 },
|
465
|
-
:raw => { :name => "RAW", :limit => 2000 }
|
474
|
+
:raw => { :name => "RAW", :limit => 2000 },
|
475
|
+
:bigint => { :name => "NUMBER", :limit => 19 }
|
466
476
|
}
|
467
477
|
# if emulate_booleans_from_strings then store booleans in VARCHAR2
|
468
478
|
NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS = NATIVE_DATABASE_TYPES.dup.merge(
|
@@ -667,22 +677,26 @@ module ActiveRecord
|
|
667
677
|
|
668
678
|
# Cast a +value+ to a type that the database understands.
|
669
679
|
def type_cast(value, column)
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
680
|
+
if column && column.cast_type.is_a?(Type::Serialized)
|
681
|
+
super
|
682
|
+
else
|
683
|
+
case value
|
684
|
+
when true, false
|
685
|
+
if emulate_booleans_from_strings || column && column.type == :string
|
686
|
+
self.class.boolean_to_string(value)
|
687
|
+
else
|
688
|
+
value ? 1 : 0
|
689
|
+
end
|
690
|
+
when Date, Time
|
691
|
+
if value.acts_like?(:time)
|
692
|
+
zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
|
693
|
+
value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
|
694
|
+
else
|
695
|
+
value
|
696
|
+
end
|
681
697
|
else
|
682
|
-
|
698
|
+
super
|
683
699
|
end
|
684
|
-
else
|
685
|
-
super
|
686
700
|
end
|
687
701
|
end
|
688
702
|
|
@@ -794,8 +808,8 @@ module ActiveRecord
|
|
794
808
|
select NVL(max(#{quote_column_name(primary_key)}),0) + 1 from #{quote_table_name(table_name)}
|
795
809
|
", new_start_value)
|
796
810
|
|
797
|
-
execute
|
798
|
-
execute
|
811
|
+
execute "DROP SEQUENCE #{quote_table_name(sequence_name)}"
|
812
|
+
execute "CREATE SEQUENCE #{quote_table_name(sequence_name)} START WITH #{new_start_value}"
|
799
813
|
end
|
800
814
|
end
|
801
815
|
|
@@ -811,8 +825,8 @@ module ActiveRecord
|
|
811
825
|
columns.each do |col|
|
812
826
|
value = attributes[col.name]
|
813
827
|
# changed sequence of next two lines - should check if value is nil before converting to yaml
|
814
|
-
next if value.
|
815
|
-
value =
|
828
|
+
next if value.blank?
|
829
|
+
value = col.cast_type.type_cast_for_database(value)
|
816
830
|
uncached do
|
817
831
|
sql = is_with_cpk ? "SELECT #{quote_column_name(col.name)} FROM #{quote_table_name(table_name)} WHERE #{klass.composite_where_clause(id)} FOR UPDATE" :
|
818
832
|
"SELECT #{quote_column_name(col.name)} FROM #{quote_table_name(table_name)} WHERE #{quote_column_name(klass.primary_key)} = #{id} FOR UPDATE"
|
@@ -835,27 +849,32 @@ module ActiveRecord
|
|
835
849
|
select_value("SELECT SYS_CONTEXT('userenv', 'session_user') FROM dual")
|
836
850
|
end
|
837
851
|
|
852
|
+
# Current database session schema
|
853
|
+
def current_schema
|
854
|
+
select_value("SELECT SYS_CONTEXT('userenv', 'current_schema') FROM dual")
|
855
|
+
end
|
856
|
+
|
838
857
|
# Default tablespace name of current user
|
839
858
|
def default_tablespace
|
840
|
-
select_value("SELECT LOWER(default_tablespace) FROM user_users WHERE username = SYS_CONTEXT('userenv', '
|
859
|
+
select_value("SELECT LOWER(default_tablespace) FROM user_users WHERE username = SYS_CONTEXT('userenv', 'current_schema')")
|
841
860
|
end
|
842
861
|
|
843
862
|
def tables(name = nil) #:nodoc:
|
844
863
|
select_values(
|
845
|
-
"SELECT DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name) FROM all_tables WHERE owner = SYS_CONTEXT('userenv', '
|
864
|
+
"SELECT DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name) FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'",
|
846
865
|
name)
|
847
866
|
end
|
848
867
|
|
849
868
|
# Will return true if database object exists (to be able to use also views and synonyms for ActiveRecord models)
|
850
869
|
def table_exists?(table_name)
|
851
|
-
(
|
870
|
+
(_owner, table_name, _db_link) = @connection.describe(table_name)
|
852
871
|
true
|
853
872
|
rescue
|
854
873
|
false
|
855
874
|
end
|
856
875
|
|
857
876
|
def materialized_views #:nodoc:
|
858
|
-
select_values("SELECT LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', '
|
877
|
+
select_values("SELECT LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', 'current_schema')")
|
859
878
|
end
|
860
879
|
|
861
880
|
cattr_accessor :all_schema_indexes #:nodoc:
|
@@ -906,7 +925,7 @@ module ActiveRecord
|
|
906
925
|
statement_parameters = $1
|
907
926
|
end
|
908
927
|
end
|
909
|
-
all_schema_indexes <<
|
928
|
+
all_schema_indexes << OracleEnhanced::IndexDefinition.new(row['table_name'], row['index_name'],
|
910
929
|
row['uniqueness'] == "UNIQUE", row['index_type'] == 'DOMAIN' ? "#{row['ityp_owner']}.#{row['ityp_name']}" : nil,
|
911
930
|
row['parameters'], statement_parameters,
|
912
931
|
row['tablespace_name'] == default_tablespace_name ? nil : row['tablespace_name'], [])
|
@@ -1038,7 +1057,7 @@ module ActiveRecord
|
|
1038
1057
|
end.map do |row|
|
1039
1058
|
limit, scale = row['limit'], row['scale']
|
1040
1059
|
if limit || scale
|
1041
|
-
row['sql_type'] += "(#{(limit ||
|
1060
|
+
row['sql_type'] += "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
|
1042
1061
|
end
|
1043
1062
|
|
1044
1063
|
if row['sql_type_owner']
|
@@ -1055,19 +1074,61 @@ module ActiveRecord
|
|
1055
1074
|
# match newlines.
|
1056
1075
|
row['data_default'].sub!(/^'(.*)'$/m, '\1')
|
1057
1076
|
row['data_default'] = nil if row['data_default'] =~ /^(null|empty_[bc]lob\(\))$/i
|
1077
|
+
# TODO: Needs better fix to fallback "N" to false
|
1078
|
+
row['data_default'] = false if (row['data_default'] == "N" && OracleEnhancedAdapter.emulate_booleans_from_strings)
|
1058
1079
|
end
|
1059
1080
|
|
1060
|
-
|
1081
|
+
# TODO: Consider to extract another method such as `get_cast_type`
|
1082
|
+
case row['sql_type']
|
1083
|
+
when /decimal|numeric|number/i
|
1084
|
+
if get_type_for_column(table_name, oracle_downcase(row['name'])) == :integer
|
1085
|
+
cast_type = ActiveRecord::OracleEnhanced::Type::Integer.new
|
1086
|
+
elsif OracleEnhancedAdapter.emulate_booleans && row['sql_type'].upcase == "NUMBER(1)"
|
1087
|
+
cast_type = Type::Boolean.new
|
1088
|
+
elsif OracleEnhancedAdapter.emulate_integers_by_column_name && OracleEnhancedAdapter.is_integer_column?(row['name'], table_name)
|
1089
|
+
cast_type = ActiveRecord::OracleEnhanced::Type::Integer.new
|
1090
|
+
else
|
1091
|
+
cast_type = lookup_cast_type(row['sql_type'])
|
1092
|
+
end
|
1093
|
+
when /char/i
|
1094
|
+
if get_type_for_column(table_name, oracle_downcase(row['name'])) == :string
|
1095
|
+
cast_type = Type::String.new
|
1096
|
+
elsif get_type_for_column(table_name, oracle_downcase(row['name'])) == :boolean
|
1097
|
+
cast_type = Type::Boolean.new
|
1098
|
+
elsif OracleEnhancedAdapter.emulate_booleans_from_strings && OracleEnhancedAdapter.is_boolean_column?(row['name'], row['sql_type'], table_name)
|
1099
|
+
cast_type = Type::Boolean.new
|
1100
|
+
else
|
1101
|
+
cast_type = lookup_cast_type(row['sql_type'])
|
1102
|
+
end
|
1103
|
+
when /date/i
|
1104
|
+
if get_type_for_column(table_name, oracle_downcase(row['name'])) == :date
|
1105
|
+
cast_type = Type::Date.new
|
1106
|
+
elsif get_type_for_column(table_name, oracle_downcase(row['name'])) == :datetime
|
1107
|
+
cast_type = Type::DateTime.new
|
1108
|
+
elsif OracleEnhancedAdapter.emulate_dates_by_column_name && OracleEnhancedAdapter.is_date_column?(row['name'], table_name)
|
1109
|
+
cast_type = Type::Date.new
|
1110
|
+
else
|
1111
|
+
cast_type = lookup_cast_type(row['sql_type'])
|
1112
|
+
end
|
1113
|
+
else
|
1114
|
+
cast_type = lookup_cast_type(row['sql_type'])
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
new_column(oracle_downcase(row['name']),
|
1061
1118
|
row['data_default'],
|
1119
|
+
cast_type,
|
1062
1120
|
row['sql_type'],
|
1063
1121
|
row['nullable'] == 'Y',
|
1064
|
-
# pass table name for table specific column definitions
|
1065
1122
|
table_name,
|
1066
|
-
|
1067
|
-
|
1123
|
+
is_virtual,
|
1124
|
+
false )
|
1068
1125
|
end
|
1069
1126
|
end
|
1070
1127
|
|
1128
|
+
def new_column(name, default, cast_type, sql_type = nil, null = true, table_name = nil, virtual=false, returning_id=false)
|
1129
|
+
OracleEnhancedColumn.new(name, default, cast_type, sql_type, null, table_name, virtual, returning_id)
|
1130
|
+
end
|
1131
|
+
|
1071
1132
|
# used just in tests to clear column cache
|
1072
1133
|
def clear_columns_cache #:nodoc:
|
1073
1134
|
@@columns_cache = nil
|
@@ -1207,6 +1268,34 @@ module ActiveRecord
|
|
1207
1268
|
|
1208
1269
|
protected
|
1209
1270
|
|
1271
|
+
def initialize_type_map(m)
|
1272
|
+
super
|
1273
|
+
# oracle
|
1274
|
+
register_class_with_limit m, %r(date)i, Type::DateTime
|
1275
|
+
register_class_with_limit m, %r(raw)i, ActiveRecord::OracleEnhanced::Type::Raw
|
1276
|
+
register_class_with_limit m, %r(timestamp)i, ActiveRecord::OracleEnhanced::Type::Timestamp
|
1277
|
+
|
1278
|
+
m.register_type(%r(NUMBER)i) do |sql_type|
|
1279
|
+
scale = extract_scale(sql_type)
|
1280
|
+
precision = extract_precision(sql_type)
|
1281
|
+
limit = extract_limit(sql_type)
|
1282
|
+
if scale == 0
|
1283
|
+
ActiveRecord::OracleEnhanced::Type::Integer.new(precision: precision, limit: limit)
|
1284
|
+
else
|
1285
|
+
Type::Decimal.new(precision: precision, scale: scale)
|
1286
|
+
end
|
1287
|
+
end
|
1288
|
+
end
|
1289
|
+
|
1290
|
+
def extract_limit(sql_type) #:nodoc:
|
1291
|
+
case sql_type
|
1292
|
+
when /^bigint/i
|
1293
|
+
19
|
1294
|
+
when /\((.*)\)/
|
1295
|
+
$1.to_i
|
1296
|
+
end
|
1297
|
+
end
|
1298
|
+
|
1210
1299
|
def translate_exception(exception, message) #:nodoc:
|
1211
1300
|
case @connection.error_code(exception)
|
1212
1301
|
when 1
|
@@ -1220,6 +1309,10 @@ module ActiveRecord
|
|
1220
1309
|
|
1221
1310
|
private
|
1222
1311
|
|
1312
|
+
def select(sql, name = nil, binds = [])
|
1313
|
+
exec_query(sql, name, binds)
|
1314
|
+
end
|
1315
|
+
|
1223
1316
|
def oracle_downcase(column_name)
|
1224
1317
|
@connection.oracle_downcase(column_name)
|
1225
1318
|
end
|
@@ -1256,12 +1349,8 @@ module ActiveRecord
|
|
1256
1349
|
end
|
1257
1350
|
|
1258
1351
|
protected
|
1259
|
-
def log(sql, name, binds = nil) #:nodoc:
|
1260
|
-
|
1261
|
-
super sql, name, binds
|
1262
|
-
else
|
1263
|
-
super sql, name
|
1264
|
-
end
|
1352
|
+
def log(sql, name = "SQL", binds = [], statement_name = nil) #:nodoc:
|
1353
|
+
super
|
1265
1354
|
ensure
|
1266
1355
|
log_dbms_output if dbms_output_enabled?
|
1267
1356
|
end
|
@@ -1289,38 +1378,47 @@ module ActiveRecord
|
|
1289
1378
|
end
|
1290
1379
|
|
1291
1380
|
# Implementation of standard schema definition statements and extensions for schema definition
|
1292
|
-
require 'active_record/connection_adapters/
|
1293
|
-
require 'active_record/connection_adapters/
|
1381
|
+
require 'active_record/connection_adapters/oracle_enhanced/schema_statements'
|
1382
|
+
require 'active_record/connection_adapters/oracle_enhanced/schema_statements_ext'
|
1294
1383
|
|
1295
1384
|
# Extensions for schema definition
|
1296
|
-
require 'active_record/connection_adapters/
|
1385
|
+
require 'active_record/connection_adapters/oracle_enhanced/schema_definitions'
|
1297
1386
|
|
1298
1387
|
# Extensions for context index definition
|
1299
|
-
require 'active_record/connection_adapters/
|
1388
|
+
require 'active_record/connection_adapters/oracle_enhanced/context_index'
|
1300
1389
|
|
1301
1390
|
# Load additional methods for composite_primary_keys support
|
1302
|
-
require 'active_record/connection_adapters/
|
1391
|
+
require 'active_record/connection_adapters/oracle_enhanced/cpk'
|
1303
1392
|
|
1304
1393
|
# Load patch for dirty tracking methods
|
1305
|
-
require 'active_record/connection_adapters/
|
1394
|
+
require 'active_record/connection_adapters/oracle_enhanced/dirty'
|
1306
1395
|
|
1307
1396
|
# Patches and enhancements for schema dumper
|
1308
|
-
require 'active_record/connection_adapters/
|
1397
|
+
require 'active_record/connection_adapters/oracle_enhanced/schema_dumper'
|
1309
1398
|
|
1310
1399
|
# Implementation of structure dump
|
1311
|
-
require 'active_record/connection_adapters/
|
1400
|
+
require 'active_record/connection_adapters/oracle_enhanced/structure_dump'
|
1312
1401
|
|
1313
|
-
require 'active_record/connection_adapters/
|
1402
|
+
require 'active_record/connection_adapters/oracle_enhanced/version'
|
1314
1403
|
|
1315
1404
|
module ActiveRecord
|
1316
|
-
autoload :OracleEnhancedProcedures, 'active_record/connection_adapters/
|
1405
|
+
autoload :OracleEnhancedProcedures, 'active_record/connection_adapters/oracle_enhanced/procedures'
|
1317
1406
|
end
|
1318
1407
|
|
1319
1408
|
# Patches and enhancements for column dumper
|
1320
|
-
require 'active_record/connection_adapters/
|
1409
|
+
require 'active_record/connection_adapters/oracle_enhanced/column_dumper'
|
1321
1410
|
|
1322
1411
|
# Moved SchemaCreation class
|
1323
|
-
require 'active_record/connection_adapters/
|
1412
|
+
require 'active_record/connection_adapters/oracle_enhanced/schema_creation'
|
1324
1413
|
|
1325
1414
|
# Moved DatabaseStetements
|
1326
|
-
require 'active_record/connection_adapters/
|
1415
|
+
require 'active_record/connection_adapters/oracle_enhanced/database_statements'
|
1416
|
+
|
1417
|
+
# Add Type:Raw
|
1418
|
+
require 'active_record/oracle_enhanced/type/raw'
|
1419
|
+
|
1420
|
+
# Add Type:Timestamp
|
1421
|
+
require 'active_record/oracle_enhanced/type/timestamp'
|
1422
|
+
|
1423
|
+
# Add OracleEnhanced::Type::Integer
|
1424
|
+
require 'active_record/oracle_enhanced/type/integer'
|
@@ -5,7 +5,7 @@ if defined?(::Rails::Railtie)
|
|
5
5
|
module ConnectionAdapters
|
6
6
|
class OracleEnhancedRailtie < ::Rails::Railtie
|
7
7
|
rake_tasks do
|
8
|
-
load 'active_record/connection_adapters/
|
8
|
+
load 'active_record/connection_adapters/oracle_enhanced/database_tasks.rb'
|
9
9
|
end
|
10
10
|
|
11
11
|
ActiveSupport.on_load(:active_record) do
|