pmacs-activerecord-oracle_enhanced-adapter 1.5.6.1 → 1.6.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -7
  3. data/History.md +126 -0
  4. data/README.md +285 -178
  5. data/Rakefile +1 -1
  6. data/VERSION +1 -1
  7. data/lib/active_record/connection_adapters/{oracle_enhanced_column.rb → oracle_enhanced/column.rb} +14 -63
  8. data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +65 -0
  9. data/lib/active_record/connection_adapters/{oracle_enhanced_connection.rb → oracle_enhanced/connection.rb} +2 -2
  10. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +347 -0
  11. data/lib/active_record/connection_adapters/{oracle_enhanced_cpk.rb → oracle_enhanced/cpk.rb} +0 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +257 -0
  13. data/lib/active_record/connection_adapters/{oracle_enhanced_database_tasks.rb → oracle_enhanced/database_tasks.rb} +0 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced/dirty.rb +40 -0
  15. data/lib/active_record/connection_adapters/{oracle_enhanced_jdbc_connection.rb → oracle_enhanced/jdbc_connection.rb} +0 -0
  16. data/lib/active_record/connection_adapters/{oracle_enhanced_oci_connection.rb → oracle_enhanced/oci_connection.rb} +0 -0
  17. data/lib/active_record/connection_adapters/{oracle_enhanced_procedures.rb → oracle_enhanced/procedures.rb} +1 -3
  18. data/lib/active_record/connection_adapters/{oracle_enhanced_schema_creation.rb → oracle_enhanced/schema_creation.rb} +34 -35
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +95 -0
  20. data/lib/active_record/connection_adapters/{oracle_enhanced_schema_dumper.rb → oracle_enhanced/schema_dumper.rb} +4 -32
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +548 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +74 -0
  23. data/lib/active_record/connection_adapters/{oracle_enhanced_structure_dump.rb → oracle_enhanced/structure_dump.rb} +28 -6
  24. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -0
  25. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +161 -68
  26. data/lib/active_record/oracle_enhanced/type/integer.rb +13 -0
  27. data/lib/active_record/oracle_enhanced/type/raw.rb +13 -0
  28. data/lib/active_record/oracle_enhanced/type/timestamp.rb +11 -0
  29. data/lib/pmacs-activerecord-oracle_enhanced-adapter.rb +1 -1
  30. data/pmacs-activerecord-oracle_enhanced-adapter.gemspec +35 -31
  31. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +6 -31
  32. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +1 -1
  33. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +2 -2
  34. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +2 -2
  35. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +75 -63
  36. data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +1 -1
  37. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +7 -13
  38. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +2 -1
  39. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +25 -178
  40. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +60 -5
  41. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +1 -0
  42. data/spec/spec_helper.rb +21 -10
  43. metadata +32 -28
  44. data/lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb +0 -77
  45. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -350
  46. data/lib/active_record/connection_adapters/oracle_enhanced_database_statements.rb +0 -262
  47. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -45
  48. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -223
  49. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -450
  50. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -267
  51. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
@@ -0,0 +1,74 @@
1
+ require 'digest/sha1'
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module OracleEnhancedSchemaStatementsExt
6
+ # Create primary key trigger (so that you can skip primary key value in INSERT statement).
7
+ # By default trigger name will be "table_name_pkt", you can override the name with
8
+ # :trigger_name option (but it is not recommended to override it as then this trigger will
9
+ # not be detected by ActiveRecord model and it will still do prefetching of sequence value).
10
+ #
11
+ # add_primary_key_trigger :users
12
+ #
13
+ # You can also create primary key trigger using +create_table+ with :primary_key_trigger
14
+ # option:
15
+ #
16
+ # create_table :users, :primary_key_trigger => true do |t|
17
+ # # ...
18
+ # end
19
+ #
20
+ def add_primary_key_trigger(table_name, options={})
21
+ # call the same private method that is used for create_table :primary_key_trigger => true
22
+ create_primary_key_trigger(table_name, options)
23
+ end
24
+
25
+ def table_definition_tablespace
26
+ # TODO: Support specifying an :index_tablespace option in create_table?
27
+ tablespace_sql = ''
28
+ if tablespace = default_tablespace_for(:index)
29
+ tablespace_sql << " USING INDEX TABLESPACE #{tablespace}"
30
+ end
31
+ tablespace_sql
32
+ end
33
+
34
+ # Add synonym to existing table or view or sequence. Can be used to create local synonym to
35
+ # remote table in other schema or in other database
36
+ # Examples:
37
+ #
38
+ # add_synonym :posts, "blog.posts"
39
+ # add_synonym :posts_seq, "blog.posts_seq"
40
+ # add_synonym :employees, "hr.employees@dblink", :force => true
41
+ #
42
+ def add_synonym(name, table_name, options = {})
43
+ sql = "CREATE"
44
+ if options[:force] == true
45
+ sql << " OR REPLACE"
46
+ end
47
+ sql << " SYNONYM #{quote_table_name(name)} FOR #{quote_table_name(table_name)}"
48
+ execute sql
49
+ end
50
+
51
+ # Remove existing synonym to table or view or sequence
52
+ # Example:
53
+ #
54
+ # remove_synonym :posts, "blog.posts"
55
+ #
56
+ def remove_synonym(name)
57
+ execute "DROP SYNONYM #{quote_table_name(name)}"
58
+ end
59
+
60
+ # get synonyms for schema dump
61
+ def synonyms #:nodoc:
62
+ select_all("SELECT synonym_name, table_owner, table_name, db_link FROM all_synonyms WHERE owner = SYS_CONTEXT('userenv', 'current_schema')").collect do |row|
63
+ OracleEnhanced::SynonymDefinition.new(oracle_downcase(row['synonym_name']),
64
+ oracle_downcase(row['table_owner']), oracle_downcase(row['table_name']), oracle_downcase(row['db_link']))
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+ end
71
+
72
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
73
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedSchemaStatementsExt
74
+ end
@@ -127,19 +127,41 @@ module ActiveRecord #:nodoc:
127
127
  if respond_to?(:foreign_keys) && (foreign_keys = foreign_keys(table["table_name"])).any?
128
128
  foreign_keys.map do |fk|
129
129
  sql = "ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
130
- sql << "#{foreign_key_definition(fk.to_table, fk.options)}"
130
+ sql << "#{foreign_key_definition(fk.to_table, fk.options) << table_definition_tablespace}"
131
131
  end
132
132
  end
133
133
  end.flatten.compact
134
134
  join_with_statement_token(fks)
135
135
  end
136
136
 
137
- def dump_schema_information #:nodoc:
138
- sm_table = ActiveRecord::Migrator.schema_migrations_table_name
139
- migrated = select_values("SELECT version FROM #{sm_table} ORDER BY version")
140
- join_with_statement_token(migrated.map{|v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" })
137
+ def foreign_key_definition(to_table, options = {}) #:nodoc:
138
+ columns = Array(options[:column] || options[:columns])
139
+
140
+ if columns.size > 1
141
+ # composite foreign key
142
+ columns_sql = columns.map {|c| quote_column_name(c)}.join(',')
143
+ references = options[:references] || columns
144
+ references_sql = references.map {|c| quote_column_name(c)}.join(',')
145
+ else
146
+ columns_sql = quote_column_name(columns.first || "#{to_table.to_s.singularize}_id")
147
+ references = options[:references] ? options[:references].first : nil
148
+ references_sql = quote_column_name(options[:primary_key] || references || "id")
149
+ end
150
+
151
+ table_name = to_table
152
+
153
+ sql = "FOREIGN KEY (#{columns_sql}) REFERENCES #{quote_table_name(table_name)}(#{references_sql})"
154
+
155
+ case options[:dependent]
156
+ when :nullify
157
+ sql << " ON DELETE SET NULL"
158
+ when :delete
159
+ sql << " ON DELETE CASCADE"
160
+ end
161
+ sql
141
162
  end
142
163
 
164
+
143
165
  # Extract all stored procedures, packages, synonyms and views.
144
166
  def structure_dump_db_stored_code #:nodoc:
145
167
  structure = []
@@ -173,7 +195,7 @@ module ActiveRecord #:nodoc:
173
195
  FROM all_synonyms
174
196
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ").each do |synonym|
175
197
  structure << "CREATE OR REPLACE #{synonym['owner'] == 'PUBLIC' ? 'PUBLIC' : '' } SYNONYM #{synonym['synonym_name']}"
176
- structure << " FOR #{synonym['table_owner']}.#{synonym['table_name']}"
198
+ structure << " FOR #{synonym['table_owner']}.#{synonym['table_name']}"
177
199
  end
178
200
 
179
201
  join_with_statement_token(structure)
@@ -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/oracle_enhanced_connection'
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/oracle_enhanced_column'
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
- (self.class.serialized_attributes.keys.include?(col.name) || self.send(:"#{col.name}_changed?")) && !self.class.readonly_attributes.to_a.include?(col.name)
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
- !!(name =~ /(^|_)id$/i)
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, field_type, table_name = nil)
330
- return true if ["CHAR(1)","VARCHAR2(1)"].include?(field_type)
331
- field_type =~ /^VARCHAR2/ && (name =~ /_flag$/i || name =~ /_yn$/i)
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
- if config.fetch(:prepared_statements) { true }
397
- @visitor = Arel::Visitors::Oracle.new self
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
- @visitor = unprepared_visitor
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
- NUMBER_MAX_PRECISION = 38
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(#{NUMBER_MAX_PRECISION}) NOT NULL PRIMARY KEY",
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 => NUMBER_MAX_PRECISION },
455
- :float => { :name => "NUMBER" },
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
- case value
671
- when true, false
672
- if emulate_booleans_from_strings || column && column.type == :string
673
- self.class.boolean_to_string(value)
674
- else
675
- value ? 1 : 0
676
- end
677
- when Date, Time
678
- if value.acts_like?(:time)
679
- zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
680
- value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
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
- value
698
+ super
683
699
  end
684
- else
685
- super
686
700
  end
687
701
  end
688
702
 
@@ -812,7 +826,7 @@ module ActiveRecord
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
828
  next if value.nil? || (value == '')
815
- value = value.to_yaml if col.text? && klass.serialized_attributes[col.name]
829
+ value = value.to_yaml if col.cast_type.is_a?(Type::Serialized) # klass.serialized_attributes[col.name]
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"
@@ -832,9 +846,9 @@ module ActiveRecord
832
846
 
833
847
  # Current database session user
834
848
  def current_user
835
- select_value("SELECT SYS_CONTEXT('userenv', 'session_user') FROM dual")
849
+ select_value("SELECT SYS_CONTEXT('userenv', 'current_schema') FROM dual")
836
850
  end
837
-
851
+
838
852
  # Current database session schema
839
853
  def current_schema
840
854
  select_value("SELECT SYS_CONTEXT('userenv', 'current_schema') FROM dual")
@@ -911,7 +925,7 @@ module ActiveRecord
911
925
  statement_parameters = $1
912
926
  end
913
927
  end
914
- all_schema_indexes << OracleEnhancedIndexDefinition.new(row['table_name'], row['index_name'],
928
+ all_schema_indexes << OracleEnhanced::IndexDefinition.new(row['table_name'], row['index_name'],
915
929
  row['uniqueness'] == "UNIQUE", row['index_type'] == 'DOMAIN' ? "#{row['ityp_owner']}.#{row['ityp_name']}" : nil,
916
930
  row['parameters'], statement_parameters,
917
931
  row['tablespace_name'] == default_tablespace_name ? nil : row['tablespace_name'], [])
@@ -1043,7 +1057,7 @@ module ActiveRecord
1043
1057
  end.map do |row|
1044
1058
  limit, scale = row['limit'], row['scale']
1045
1059
  if limit || scale
1046
- row['sql_type'] += "(#{(limit || NUMBER_MAX_PRECISION).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
1060
+ row['sql_type'] += "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
1047
1061
  end
1048
1062
 
1049
1063
  if row['sql_type_owner']
@@ -1060,19 +1074,61 @@ module ActiveRecord
1060
1074
  # match newlines.
1061
1075
  row['data_default'].sub!(/^'(.*)'$/m, '\1')
1062
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"
1079
+ end
1080
+
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'])
1063
1115
  end
1064
1116
 
1065
- OracleEnhancedColumn.new(oracle_downcase(row['name']),
1117
+ new_column(oracle_downcase(row['name']),
1066
1118
  row['data_default'],
1119
+ cast_type,
1067
1120
  row['sql_type'],
1068
1121
  row['nullable'] == 'Y',
1069
- # pass table name for table specific column definitions
1070
1122
  table_name,
1071
- # pass column type if specified in class definition
1072
- get_type_for_column(table_name, oracle_downcase(row['name'])), is_virtual)
1123
+ is_virtual,
1124
+ false )
1073
1125
  end
1074
1126
  end
1075
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
+
1076
1132
  # used just in tests to clear column cache
1077
1133
  def clear_columns_cache #:nodoc:
1078
1134
  @@columns_cache = nil
@@ -1212,6 +1268,34 @@ module ActiveRecord
1212
1268
 
1213
1269
  protected
1214
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
+
1215
1299
  def translate_exception(exception, message) #:nodoc:
1216
1300
  case @connection.error_code(exception)
1217
1301
  when 1
@@ -1225,6 +1309,10 @@ module ActiveRecord
1225
1309
 
1226
1310
  private
1227
1311
 
1312
+ def select(sql, name = nil, binds = [])
1313
+ exec_query(sql, name, binds)
1314
+ end
1315
+
1228
1316
  def oracle_downcase(column_name)
1229
1317
  @connection.oracle_downcase(column_name)
1230
1318
  end
@@ -1261,12 +1349,8 @@ module ActiveRecord
1261
1349
  end
1262
1350
 
1263
1351
  protected
1264
- def log(sql, name, binds = nil) #:nodoc:
1265
- if binds
1266
- super sql, name, binds
1267
- else
1268
- super sql, name
1269
- end
1352
+ def log(sql, name = "SQL", binds = [], statement_name = nil) #:nodoc:
1353
+ super
1270
1354
  ensure
1271
1355
  log_dbms_output if dbms_output_enabled?
1272
1356
  end
@@ -1294,38 +1378,47 @@ module ActiveRecord
1294
1378
  end
1295
1379
 
1296
1380
  # Implementation of standard schema definition statements and extensions for schema definition
1297
- require 'active_record/connection_adapters/oracle_enhanced_schema_statements'
1298
- require 'active_record/connection_adapters/oracle_enhanced_schema_statements_ext'
1381
+ require 'active_record/connection_adapters/oracle_enhanced/schema_statements'
1382
+ require 'active_record/connection_adapters/oracle_enhanced/schema_statements_ext'
1299
1383
 
1300
1384
  # Extensions for schema definition
1301
- require 'active_record/connection_adapters/oracle_enhanced_schema_definitions'
1385
+ require 'active_record/connection_adapters/oracle_enhanced/schema_definitions'
1302
1386
 
1303
1387
  # Extensions for context index definition
1304
- require 'active_record/connection_adapters/oracle_enhanced_context_index'
1388
+ require 'active_record/connection_adapters/oracle_enhanced/context_index'
1305
1389
 
1306
1390
  # Load additional methods for composite_primary_keys support
1307
- require 'active_record/connection_adapters/oracle_enhanced_cpk'
1391
+ require 'active_record/connection_adapters/oracle_enhanced/cpk'
1308
1392
 
1309
1393
  # Load patch for dirty tracking methods
1310
- require 'active_record/connection_adapters/oracle_enhanced_dirty'
1394
+ require 'active_record/connection_adapters/oracle_enhanced/dirty'
1311
1395
 
1312
1396
  # Patches and enhancements for schema dumper
1313
- require 'active_record/connection_adapters/oracle_enhanced_schema_dumper'
1397
+ require 'active_record/connection_adapters/oracle_enhanced/schema_dumper'
1314
1398
 
1315
1399
  # Implementation of structure dump
1316
- require 'active_record/connection_adapters/oracle_enhanced_structure_dump'
1400
+ require 'active_record/connection_adapters/oracle_enhanced/structure_dump'
1317
1401
 
1318
- require 'active_record/connection_adapters/oracle_enhanced_version'
1402
+ require 'active_record/connection_adapters/oracle_enhanced/version'
1319
1403
 
1320
1404
  module ActiveRecord
1321
- autoload :OracleEnhancedProcedures, 'active_record/connection_adapters/oracle_enhanced_procedures'
1405
+ autoload :OracleEnhancedProcedures, 'active_record/connection_adapters/oracle_enhanced/procedures'
1322
1406
  end
1323
1407
 
1324
1408
  # Patches and enhancements for column dumper
1325
- require 'active_record/connection_adapters/oracle_enhanced_column_dumper'
1409
+ require 'active_record/connection_adapters/oracle_enhanced/column_dumper'
1326
1410
 
1327
1411
  # Moved SchemaCreation class
1328
- require 'active_record/connection_adapters/oracle_enhanced_schema_creation'
1412
+ require 'active_record/connection_adapters/oracle_enhanced/schema_creation'
1329
1413
 
1330
1414
  # Moved DatabaseStetements
1331
- require 'active_record/connection_adapters/oracle_enhanced_database_statements'
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'