activerecord-oracle_enhanced-adapter 1.5.6 → 1.6.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|