activerecord-oracle_enhanced-adapter 6.1.4 → 7.0.1

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +78 -0
  3. data/README.md +12 -1
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +1 -1
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +2 -2
  7. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +22 -13
  8. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +3 -3
  9. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +1 -1
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +19 -22
  11. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +1 -1
  12. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +14 -8
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +1 -1
  14. data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +4 -4
  15. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +18 -18
  16. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +1 -1
  17. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +6 -6
  18. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +16 -16
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +1 -1
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +1 -1
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +6 -6
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +37 -27
  23. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +30 -29
  24. data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +1 -1
  25. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +123 -98
  26. data/lib/arel/visitors/oracle.rb +6 -2
  27. data/lib/arel/visitors/oracle12.rb +4 -0
  28. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +18 -1
  29. data/spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb +2 -2
  30. data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +5 -5
  31. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +3 -3
  32. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +5 -5
  33. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +10 -10
  34. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +34 -7
  35. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +5 -5
  36. data/spec/active_record/oracle_enhanced/type/custom_spec.rb +88 -0
  37. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +2 -2
  38. metadata +22 -6
@@ -63,9 +63,9 @@ require "active_record/type/oracle_enhanced/timestampltz"
63
63
  require "active_record/type/oracle_enhanced/character_string"
64
64
 
65
65
  module ActiveRecord
66
- module ConnectionHandling #:nodoc:
66
+ module ConnectionHandling # :nodoc:
67
67
  # Establishes a connection to the database that's used by all Active Record objects.
68
- def oracle_enhanced_connection(config) #:nodoc:
68
+ def oracle_enhanced_connection(config) # :nodoc:
69
69
  if config[:emulate_oracle_adapter] == true
70
70
  # allows the enhanced adapter to look like the OracleAdapter. Useful to pick up
71
71
  # conditionals in the rails activerecord test suite
@@ -79,7 +79,7 @@ module ActiveRecord
79
79
  end
80
80
  end
81
81
 
82
- module ConnectionAdapters #:nodoc:
82
+ module ConnectionAdapters # :nodoc:
83
83
  # Oracle enhanced adapter will work with both
84
84
  # CRuby ruby-oci8 gem (which provides interface to Oracle OCI client)
85
85
  # or with JRuby and Oracle JDBC driver.
@@ -120,6 +120,7 @@ module ActiveRecord
120
120
  # * <tt>:schema</tt> - database schema which holds schema objects.
121
121
  # * <tt>:tcp_keepalive</tt> - TCP keepalive is enabled for OCI client, defaults to true
122
122
  # * <tt>:tcp_keepalive_time</tt> - TCP keepalive time for OCI client, defaults to 600
123
+ # * <tt>:jdbc_statement_cache_size</tt> - number of cached SQL cursors to keep open, disabled per default (for unpooled JDBC only)
123
124
  #
124
125
  # Optionals NLS parameters:
125
126
  #
@@ -248,7 +249,7 @@ module ActiveRecord
248
249
 
249
250
  ADAPTER_NAME = "OracleEnhanced"
250
251
 
251
- def adapter_name #:nodoc:
252
+ def adapter_name # :nodoc:
252
253
  ADAPTER_NAME
253
254
  end
254
255
 
@@ -272,11 +273,11 @@ module ActiveRecord
272
273
  StatementPool.new(self.class.type_cast_config_to_integer(@config[:statement_limit]))
273
274
  end
274
275
 
275
- def supports_savepoints? #:nodoc:
276
+ def supports_savepoints? # :nodoc:
276
277
  true
277
278
  end
278
279
 
279
- def supports_transaction_isolation? #:nodoc:
280
+ def supports_transaction_isolation? # :nodoc:
280
281
  true
281
282
  end
282
283
 
@@ -359,7 +360,7 @@ module ActiveRecord
359
360
  end
360
361
  end
361
362
 
362
- #:stopdoc:
363
+ # :stopdoc:
363
364
  DEFAULT_NLS_PARAMETERS = {
364
365
  nls_calendar: nil,
365
366
  nls_comp: nil,
@@ -378,13 +379,13 @@ module ActiveRecord
378
379
  nls_time_tz_format: nil
379
380
  }
380
381
 
381
- #:stopdoc:
382
+ # :stopdoc:
382
383
  FIXED_NLS_PARAMETERS = {
383
384
  nls_date_format: "YYYY-MM-DD HH24:MI:SS",
384
385
  nls_timestamp_format: "YYYY-MM-DD HH24:MI:SS:FF6"
385
386
  }
386
387
 
387
- #:stopdoc:
388
+ # :stopdoc:
388
389
  NATIVE_DATABASE_TYPES = {
389
390
  primary_key: "NUMBER(38) NOT NULL PRIMARY KEY",
390
391
  string: { name: "VARCHAR2", limit: 255 },
@@ -408,9 +409,9 @@ module ActiveRecord
408
409
  NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS = NATIVE_DATABASE_TYPES.dup.merge(
409
410
  boolean: { name: "VARCHAR2", limit: 1 }
410
411
  )
411
- #:startdoc:
412
+ # :startdoc:
412
413
 
413
- def native_database_types #:nodoc:
414
+ def native_database_types # :nodoc:
414
415
  emulate_booleans_from_strings ? NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS : NATIVE_DATABASE_TYPES
415
416
  end
416
417
 
@@ -420,10 +421,10 @@ module ActiveRecord
420
421
  # If SQL statement fails due to lost connection then reconnect
421
422
  # and retry SQL statement if autocommit mode is enabled.
422
423
  # By default this functionality is disabled.
423
- attr_reader :auto_retry #:nodoc:
424
+ attr_reader :auto_retry # :nodoc:
424
425
  @auto_retry = false
425
426
 
426
- def auto_retry=(value) #:nodoc:
427
+ def auto_retry=(value) # :nodoc:
427
428
  @auto_retry = value
428
429
  @connection.auto_retry = value if @connection
429
430
  end
@@ -434,7 +435,7 @@ module ActiveRecord
434
435
  end
435
436
 
436
437
  # Returns true if the connection is active.
437
- def active? #:nodoc:
438
+ def active? # :nodoc:
438
439
  # Pings the connection to check if it's still good. Note that an
439
440
  # #active? method is also available, but that simply returns the
440
441
  # last known state, which isn't good enough if the connection has
@@ -445,7 +446,7 @@ module ActiveRecord
445
446
  end
446
447
 
447
448
  # Reconnects to the database.
448
- def reconnect! #:nodoc:
449
+ def reconnect! # :nodoc:
449
450
  super
450
451
  @connection.reset!
451
452
  rescue OracleEnhanced::ConnectionException => e
@@ -458,7 +459,7 @@ module ActiveRecord
458
459
  end
459
460
 
460
461
  # Disconnects from the database.
461
- def disconnect! #:nodoc:
462
+ def disconnect! # :nodoc:
462
463
  super
463
464
  @connection.logoff rescue nil
464
465
  end
@@ -491,12 +492,12 @@ module ActiveRecord
491
492
  do_not_prefetch = @do_not_prefetch_primary_key[table_name]
492
493
  if do_not_prefetch.nil?
493
494
  owner, desc_table_name = @connection.describe(table_name)
494
- @do_not_prefetch_primary_key [table_name] = do_not_prefetch = !has_primary_key?(table_name, owner, desc_table_name)
495
+ @do_not_prefetch_primary_key[table_name] = do_not_prefetch = !has_primary_key?(table_name, owner, desc_table_name)
495
496
  end
496
497
  !do_not_prefetch
497
498
  end
498
499
 
499
- def reset_pk_sequence!(table_name, primary_key = nil, sequence_name = nil) #:nodoc:
500
+ def reset_pk_sequence!(table_name, primary_key = nil, sequence_name = nil) # :nodoc:
500
501
  return nil unless data_source_exists?(table_name)
501
502
  unless primary_key && sequence_name
502
503
  # *Note*: Only primary key is implemented - sequence will be nil.
@@ -561,7 +562,7 @@ module ActiveRecord
561
562
  def column_definitions(table_name)
562
563
  (owner, desc_table_name) = @connection.describe(table_name)
563
564
 
564
- select_all(<<~SQL.squish, "SCHEMA")
565
+ select_all(<<~SQL.squish, "SCHEMA", [bind_string("owner", owner), bind_string("table_name", desc_table_name)])
565
566
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cols.column_name AS name, cols.data_type AS sql_type,
566
567
  cols.data_default, cols.nullable, cols.virtual_column, cols.hidden_column,
567
568
  cols.data_type_owner AS sql_type_owner,
@@ -574,8 +575,8 @@ module ActiveRecord
574
575
  DECODE(data_type, 'NUMBER', data_scale, NULL) AS scale,
575
576
  comments.comments as column_comment
576
577
  FROM all_tab_cols cols, all_col_comments comments
577
- WHERE cols.owner = '#{owner}'
578
- AND cols.table_name = #{quote(desc_table_name)}
578
+ WHERE cols.owner = :owner
579
+ AND cols.table_name = :table_name
579
580
  AND cols.hidden_column = 'NO'
580
581
  AND cols.owner = comments.owner
581
582
  AND cols.table_name = comments.table_name
@@ -590,22 +591,22 @@ module ActiveRecord
590
591
 
591
592
  # Find a table's primary key and sequence.
592
593
  # *Note*: Only primary key is implemented - sequence will be nil.
593
- def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil) #:nodoc:
594
+ def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil) # :nodoc:
594
595
  (owner, desc_table_name) = @connection.describe(table_name)
595
596
 
596
- seqs = select_values(<<~SQL.squish, "SCHEMA")
597
+ seqs = select_values_forcing_binds(<<~SQL.squish, "SCHEMA", [bind_string("owner", owner), bind_string("sequence_name", default_sequence_name(desc_table_name))])
597
598
  select /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ us.sequence_name
598
599
  from all_sequences us
599
- where us.sequence_owner = '#{owner}'
600
- and us.sequence_name = upper(#{quote(default_sequence_name(desc_table_name))})
600
+ where us.sequence_owner = :owner
601
+ and us.sequence_name = upper(:sequence_name)
601
602
  SQL
602
603
 
603
604
  # changed back from user_constraints to all_constraints for consistency
604
- pks = select_values(<<~SQL.squish, "SCHEMA")
605
+ pks = select_values_forcing_binds(<<~SQL.squish, "SCHEMA", [bind_string("owner", owner), bind_string("table_name", desc_table_name)])
605
606
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cc.column_name
606
607
  FROM all_constraints c, all_cons_columns cc
607
- WHERE c.owner = '#{owner}'
608
- AND c.table_name = #{quote(desc_table_name)}
608
+ WHERE c.owner = :owner
609
+ AND c.table_name = :table_name
609
610
  AND c.constraint_type = 'P'
610
611
  AND cc.owner = c.owner
611
612
  AND cc.constraint_name = c.constraint_name
@@ -628,14 +629,14 @@ module ActiveRecord
628
629
  pk_and_sequence && pk_and_sequence.first
629
630
  end
630
631
 
631
- def has_primary_key?(table_name, owner = nil, desc_table_name = nil) #:nodoc:
632
+ def has_primary_key?(table_name, owner = nil, desc_table_name = nil) # :nodoc:
632
633
  !pk_and_sequence_for(table_name, owner, desc_table_name).nil?
633
634
  end
634
635
 
635
636
  def primary_keys(table_name) # :nodoc:
636
637
  (_owner, desc_table_name) = @connection.describe(table_name)
637
638
 
638
- pks = select_values(<<~SQL.squish, "SCHEMA", [bind_string("table_name", desc_table_name)])
639
+ pks = select_values_forcing_binds(<<~SQL.squish, "SCHEMA", [bind_string("table_name", desc_table_name)])
639
640
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ cc.column_name
640
641
  FROM all_constraints c, all_cons_columns cc
641
642
  WHERE c.owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -648,7 +649,7 @@ module ActiveRecord
648
649
  pks.map { |pk| oracle_downcase(pk) }
649
650
  end
650
651
 
651
- def columns_for_distinct(columns, orders) #:nodoc:
652
+ def columns_for_distinct(columns, orders) # :nodoc:
652
653
  # construct a valid columns name for DISTINCT clause,
653
654
  # ie. one that includes the ORDER BY columns, using FIRST_VALUE such that
654
655
  # the inclusion of these columns doesn't invalidate the DISTINCT
@@ -664,8 +665,8 @@ module ActiveRecord
664
665
  [super, *order_columns].join(", ")
665
666
  end
666
667
 
667
- def temporary_table?(table_name) #:nodoc:
668
- select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase)]) == "Y"
668
+ def temporary_table?(table_name) # :nodoc:
669
+ select_value_forcing_binds(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase)]) == "Y"
669
670
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
670
671
  temporary FROM all_tables WHERE table_name = :table_name and owner = SYS_CONTEXT('userenv', 'current_schema')
671
672
  SQL
@@ -689,82 +690,106 @@ module ActiveRecord
689
690
  end
690
691
  end
691
692
 
692
- private
693
- def initialize_type_map(m = type_map)
694
- super
695
- # oracle
696
- register_class_with_precision m, %r(WITH TIME ZONE)i, Type::OracleEnhanced::TimestampTz
697
- register_class_with_precision m, %r(WITH LOCAL TIME ZONE)i, Type::OracleEnhanced::TimestampLtz
698
- register_class_with_limit m, %r(raw)i, Type::OracleEnhanced::Raw
699
- register_class_with_limit m, %r{^(char)}i, Type::OracleEnhanced::CharacterString
700
- register_class_with_limit m, %r{^(nchar)}i, Type::OracleEnhanced::String
701
- register_class_with_limit m, %r(varchar)i, Type::OracleEnhanced::String
702
- register_class_with_limit m, %r(clob)i, Type::OracleEnhanced::Text
703
- register_class_with_limit m, %r(nclob)i, Type::OracleEnhanced::NationalCharacterText
704
-
705
- m.register_type "NCHAR", Type::OracleEnhanced::NationalCharacterString.new
706
- m.alias_type %r(NVARCHAR2)i, "NCHAR"
707
-
708
- m.register_type(%r(NUMBER)i) do |sql_type|
709
- scale = extract_scale(sql_type)
710
- precision = extract_precision(sql_type)
711
- limit = extract_limit(sql_type)
712
- if scale == 0
713
- Type::OracleEnhanced::Integer.new(precision: precision, limit: limit)
714
- else
715
- Type::Decimal.new(precision: precision, scale: scale)
693
+ class << self
694
+ private
695
+ def initialize_type_map(m)
696
+ super
697
+ # oracle
698
+ register_class_with_precision m, %r(WITH TIME ZONE)i, Type::OracleEnhanced::TimestampTz
699
+ register_class_with_precision m, %r(WITH LOCAL TIME ZONE)i, Type::OracleEnhanced::TimestampLtz
700
+ register_class_with_limit m, %r(raw)i, Type::OracleEnhanced::Raw
701
+ register_class_with_limit m, %r{^(char)}i, Type::OracleEnhanced::CharacterString
702
+ register_class_with_limit m, %r{^(nchar)}i, Type::OracleEnhanced::String
703
+ register_class_with_limit m, %r(varchar)i, Type::OracleEnhanced::String
704
+ register_class_with_limit m, %r(clob)i, Type::OracleEnhanced::Text
705
+ register_class_with_limit m, %r(nclob)i, Type::OracleEnhanced::NationalCharacterText
706
+
707
+ m.register_type "NCHAR", Type::OracleEnhanced::NationalCharacterString.new
708
+ m.alias_type %r(NVARCHAR2)i, "NCHAR"
709
+
710
+ m.register_type(%r(NUMBER)i) do |sql_type|
711
+ scale = extract_scale(sql_type)
712
+ precision = extract_precision(sql_type)
713
+ limit = extract_limit(sql_type)
714
+ if scale == 0
715
+ Type::OracleEnhanced::Integer.new(precision: precision, limit: limit)
716
+ else
717
+ Type::Decimal.new(precision: precision, scale: scale)
718
+ end
716
719
  end
717
- end
718
720
 
719
- if OracleEnhancedAdapter.emulate_booleans
720
- m.register_type %r(^NUMBER\(1\))i, Type::Boolean.new
721
+ if OracleEnhancedAdapter.emulate_booleans
722
+ m.register_type %r(^NUMBER\(1\))i, Type::Boolean.new
723
+ end
721
724
  end
722
- end
725
+ end
723
726
 
724
- def extract_value_from_default(default)
725
- case default
726
- when String
727
- default.gsub("''", "'")
728
- else
729
- default
730
- end
731
- end
727
+ TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
732
728
 
733
- def extract_limit(sql_type) #:nodoc:
734
- case sql_type
735
- when /^bigint/i
736
- 19
737
- when /\((.*)\)/
738
- $1.to_i
739
- end
729
+ def type_map
730
+ TYPE_MAP
731
+ end
732
+
733
+ def extract_value_from_default(default)
734
+ case default
735
+ when String
736
+ default.gsub("''", "'")
737
+ else
738
+ default
740
739
  end
740
+ end
741
741
 
742
- def translate_exception(exception, message:, sql:, binds:) #:nodoc:
743
- case @connection.error_code(exception)
744
- when 1
745
- RecordNotUnique.new(message, sql: sql, binds: binds)
746
- when 60
747
- Deadlocked.new(message)
748
- when 900, 904, 942, 955, 1418, 2289, 2449, 17008
749
- ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
750
- when 1400
751
- ActiveRecord::NotNullViolation.new(message, sql: sql, binds: binds)
752
- when 2291, 2292
753
- InvalidForeignKey.new(message, sql: sql, binds: binds)
754
- when 12899
755
- ValueTooLong.new(message, sql: sql, binds: binds)
756
- else
757
- super
758
- end
742
+ def extract_limit(sql_type) # :nodoc:
743
+ case sql_type
744
+ when /^bigint/i
745
+ 19
746
+ when /\((.*)\)/
747
+ $1.to_i
759
748
  end
749
+ end
760
750
 
761
- # create bind object for type String
762
- def bind_string(name, value)
763
- ActiveRecord::Relation::QueryAttribute.new(name, value, Type::OracleEnhanced::String.new)
751
+ def translate_exception(exception, message:, sql:, binds:) # :nodoc:
752
+ case @connection.error_code(exception)
753
+ when 1
754
+ RecordNotUnique.new(message, sql: sql, binds: binds)
755
+ when 60
756
+ Deadlocked.new(message)
757
+ when 900, 904, 942, 955, 1418, 2289, 2449, 17008
758
+ ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
759
+ when 1400
760
+ ActiveRecord::NotNullViolation.new(message, sql: sql, binds: binds)
761
+ when 2291, 2292
762
+ InvalidForeignKey.new(message, sql: sql, binds: binds)
763
+ when 12899
764
+ ValueTooLong.new(message, sql: sql, binds: binds)
765
+ else
766
+ super
764
767
  end
768
+ end
769
+
770
+ # create bind object for type String
771
+ def bind_string(name, value)
772
+ ActiveRecord::Relation::QueryAttribute.new(name, value, Type::OracleEnhanced::String.new)
773
+ end
774
+
775
+ # call select_values using binds even if surrounding SQL preparation/execution is done + # with conn.unprepared_statement (like AR.to_sql)
776
+ def select_values_forcing_binds(arel, name, binds)
777
+ # remove possible force of unprepared SQL during dictionary access
778
+ unprepared_statement_forced = prepared_statements_disabled_cache.include?(object_id)
779
+ prepared_statements_disabled_cache.delete(object_id) if unprepared_statement_forced
780
+
781
+ select_values(arel, name, binds)
782
+ ensure
783
+ # Restore unprepared_statement setting for surrounding SQL
784
+ prepared_statements_disabled_cache.add(object_id) if unprepared_statement_forced
785
+ end
786
+
787
+ def select_value_forcing_binds(arel, name, binds)
788
+ single_value_from_rows(select_values_forcing_binds(arel, name, binds))
789
+ end
765
790
 
766
- ActiveRecord::Type.register(:boolean, Type::OracleEnhanced::Boolean, adapter: :oracleenhanced)
767
- ActiveRecord::Type.register(:json, Type::OracleEnhanced::Json, adapter: :oracleenhanced)
791
+ ActiveRecord::Type.register(:boolean, Type::OracleEnhanced::Boolean, adapter: :oracle_enhanced)
792
+ ActiveRecord::Type.register(:json, Type::OracleEnhanced::Json, adapter: :oracle_enhanced)
768
793
  end
769
794
  end
770
795
  end
@@ -28,7 +28,7 @@ module Arel # :nodoc: all
28
28
 
29
29
  collector = super(o, collector)
30
30
 
31
- if offset.expr.is_a? Nodes::BindParam
31
+ if offset.expr.type.is_a? ActiveModel::Type::Value
32
32
  collector << ") raw_sql_ WHERE rownum <= ("
33
33
  collector = visit offset.expr, collector
34
34
  collector << " + "
@@ -38,7 +38,7 @@ module Arel # :nodoc: all
38
38
  return collector
39
39
  else
40
40
  collector << ") raw_sql_
41
- WHERE rownum <= #{offset.expr.to_i + limit}
41
+ WHERE rownum <= #{offset.expr.value_before_type_cast + limit.value_before_type_cast}
42
42
  )
43
43
  WHERE "
44
44
  return visit(offset, collector)
@@ -192,6 +192,10 @@ module Arel # :nodoc: all
192
192
  array
193
193
  end
194
194
 
195
+ def visit_ActiveModel_Attribute(o, collector)
196
+ collector.add_bind(o) { |i| ":a#{i}" }
197
+ end
198
+
195
199
  def visit_Arel_Nodes_BindParam(o, collector)
196
200
  collector.add_bind(o.value) { |i| ":a#{i}" }
197
201
  end
@@ -99,6 +99,10 @@ module Arel # :nodoc: all
99
99
  super
100
100
  end
101
101
 
102
+ def visit_ActiveModel_Attribute(o, collector)
103
+ collector.add_bind(o) { |i| ":a#{i}" }
104
+ end
105
+
102
106
  def visit_Arel_Nodes_BindParam(o, collector)
103
107
  collector.add_bind(o.value) { |i| ":a#{i}" }
104
108
  end
@@ -41,6 +41,23 @@ describe "OracleEnhancedAdapter establish connection" do
41
41
  expect(ActiveRecord::Base.connection.select_value("select value from v$parameter where name = 'cursor_sharing'")).to eq("EXACT")
42
42
  end
43
43
 
44
+ it "should not use JDBC statement caching" do
45
+ if ORACLE_ENHANCED_CONNECTION == :jdbc
46
+ ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS)
47
+ expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to eq(false)
48
+ expect(ActiveRecord::Base.connection.raw_connection.getStatementCacheSize).to eq(-1)
49
+ end
50
+ end
51
+
52
+ it "should use JDBC statement caching" do
53
+ if ORACLE_ENHANCED_CONNECTION == :jdbc
54
+ ActiveRecord::Base.establish_connection(SYSTEM_CONNECTION_PARAMS.merge(jdbc_statement_cache_size: 100))
55
+ expect(ActiveRecord::Base.connection.raw_connection.getImplicitCachingEnabled).to eq(true)
56
+ expect(ActiveRecord::Base.connection.raw_connection.getStatementCacheSize).to eq(100)
57
+ # else: don't raise error if OCI connection has parameter "jdbc_statement_cache_size", still ignore it
58
+ end
59
+ end
60
+
44
61
  it "should connect to database using service_name" do
45
62
  ActiveRecord::Base.establish_connection(SERVICE_NAME_CONNECTION_PARAMS)
46
63
  expect(ActiveRecord::Base.connection).not_to be_nil
@@ -215,7 +232,7 @@ describe "OracleEnhancedConnection" do
215
232
  end
216
233
 
217
234
  it "should respect default_timezone = :utc than time_zone setting" do
218
- # it expects that ActiveRecord::Base.default_timezone = :utc
235
+ # it expects that ActiveRecord.default_timezone = :utc
219
236
  ActiveRecord::ConnectionAdapters::OracleEnhanced::Connection.create(CONNECTION_WITH_TIMEZONE_PARAMS)
220
237
  post = Post.create!
221
238
  created_at = post.created_at
@@ -326,7 +326,7 @@ describe "OracleEnhancedAdapter context index" do
326
326
  it "should dump definition of single column index" do
327
327
  @conn.add_context_index :posts, :title
328
328
  output = dump_table_schema "posts"
329
- expect(output).to match(/add_context_index "posts", \["title"\], name: \"index_posts_on_title\"$/)
329
+ expect(output).to match(/add_context_index "posts", \["title"\], name: "index_posts_on_title"$/)
330
330
  @conn.remove_context_index :posts, :title
331
331
  end
332
332
 
@@ -375,7 +375,7 @@ describe "OracleEnhancedAdapter context index" do
375
375
  sub_query = "SELECT comments.author AS comment_author, comments.body AS comment_body\nFROM comments\nWHERE comments.post_id = :id"
376
376
  @conn.add_context_index :posts, [:title, :body, sub_query], options
377
377
  output = dump_table_schema "posts"
378
- expect(output).to match(/add_context_index "posts", \[:title, :body, "#{sub_query.gsub(/\n/, ' ')}"\], #{options.inspect[1..-2]}$/)
378
+ expect(output).to match(/add_context_index "posts", \[:title, :body, "#{sub_query.tr("\n", ' ')}"\], #{options.inspect[1..-2]}$/)
379
379
  @conn.remove_context_index :posts, name: "post_and_comments_index"
380
380
  end
381
381
  end
@@ -210,8 +210,8 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
210
210
  expect(@employee.first_name).to eq("First")
211
211
  end
212
212
 
213
- it "should not update record if nothing is changed and partial writes are enabled" do
214
- TestEmployee.partial_writes = true
213
+ it "should not update record if nothing is changed and partial updates are enabled" do
214
+ TestEmployee.partial_updates = true
215
215
  @employee = TestEmployee.create(
216
216
  first_name: "First",
217
217
  last_name: "Last",
@@ -223,8 +223,8 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
223
223
  expect(@employee.version).to eq(1)
224
224
  end
225
225
 
226
- it "should update record if nothing is changed and partial writes are disabled" do
227
- TestEmployee.partial_writes = false
226
+ it "should update record if nothing is changed and partial updates are disabled" do
227
+ TestEmployee.partial_updates = false
228
228
  @employee = TestEmployee.create(
229
229
  first_name: "First",
230
230
  last_name: "Last",
@@ -316,7 +316,7 @@ describe "OracleEnhancedAdapter custom methods for create, update and destroy" d
316
316
  end
317
317
 
318
318
  it "should log update record" do
319
- (TestEmployee.partial_writes = false) rescue nil
319
+ (TestEmployee.partial_updates = false) rescue nil
320
320
  @employee = TestEmployee.create(
321
321
  first_name: "First",
322
322
  last_name: "Last",
@@ -71,7 +71,7 @@ describe "OracleEnhancedAdapter schema dump" do
71
71
 
72
72
  it "should be able to dump default values using special characters" do
73
73
  output = dump_table_schema "test_defaults"
74
- expect(output).to match(/t.string \"special_c\", default: "\\n"/)
74
+ expect(output).to match(/t.string "special_c", default: "\\n"/)
75
75
  end
76
76
  end
77
77
 
@@ -104,7 +104,7 @@ describe "OracleEnhancedAdapter schema dump" do
104
104
 
105
105
  it "should be able to dump ntext columns" do
106
106
  output = dump_table_schema "test_ntexts"
107
- expect(output).to match(/t.ntext \"ntext_column\"/)
107
+ expect(output).to match(/t.ntext "ntext_column"/)
108
108
  end
109
109
  end
110
110
 
@@ -370,7 +370,7 @@ describe "OracleEnhancedAdapter schema dump" do
370
370
  expect(output).to match(/t\.virtual "full_name",(\s*)type: :string,(\s*)limit: 512,(\s*)as: "\\"FIRST_NAME\\"\|\|', '\|\|\\"LAST_NAME\\""/)
371
371
  expect(output).to match(/t\.virtual "short_name",(\s*)type: :string,(\s*)limit: 300,(\s*)as:(.*)/)
372
372
  expect(output).to match(/t\.virtual "full_name_length",(\s*)type: :integer,(\s*)precision: 38,(\s*)as:(.*)/)
373
- expect(output).to match(/t\.virtual "name_ratio",(\s*)as:(.*)\"$/) # no :type
373
+ expect(output).to match(/t\.virtual "name_ratio",(\s*)as:(.*)"$/) # no :type
374
374
  expect(output).to match(/t\.virtual "abbrev_name",(\s*)type: :string,(\s*)limit: 100,(\s*)as:(.*)/)
375
375
  expect(output).to match(/t\.virtual "field_with_leading_space",(\s*)type: :string,(\s*)limit: 300,(\s*)as: "' '\|\|\\"FIRST_NAME\\"\|\|' '"/)
376
376
  end
@@ -333,7 +333,7 @@ describe "OracleEnhancedAdapter schema definition" do
333
333
  ("index_test_employees_on_first_name_and_middle_name_and_last_name"))
334
334
  else
335
335
  expect(@conn.index_name("test_employees", column: ["first_name", "middle_name", "last_name"])).to eq(
336
- "i" + Digest::SHA1.hexdigest("index_test_employees_on_first_name_and_middle_name_and_last_name")[0, 29]
336
+ "i" + OpenSSL::Digest::SHA1.hexdigest("index_test_employees_on_first_name_and_middle_name_and_last_name")[0, 29]
337
337
  )
338
338
  end
339
339
  end
@@ -455,7 +455,7 @@ end
455
455
  end
456
456
 
457
457
  it "should add foreign key" do
458
- fk_name = "fk_rails_#{Digest::SHA256.hexdigest("test_comments_test_post_id_fk").first(10)}"
458
+ fk_name = "fk_rails_#{OpenSSL::Digest::SHA256.hexdigest("test_comments_test_post_id_fk").first(10)}"
459
459
 
460
460
  schema_define do
461
461
  add_foreign_key :test_comments, :test_posts
@@ -475,7 +475,7 @@ end
475
475
  end
476
476
 
477
477
  it "should add foreign key with column" do
478
- fk_name = "fk_rails_#{Digest::SHA256.hexdigest("test_comments_post_id_fk").first(10)}"
478
+ fk_name = "fk_rails_#{OpenSSL::Digest::SHA256.hexdigest("test_comments_post_id_fk").first(10)}"
479
479
 
480
480
  schema_define do
481
481
  add_foreign_key :test_comments, :test_posts, column: "post_id"
@@ -1122,13 +1122,13 @@ end
1122
1122
 
1123
1123
  before(:each) do
1124
1124
  @conn.instance_variable_set :@would_execute_sql, @would_execute_sql = +""
1125
- class <<@conn
1125
+ class << @conn
1126
1126
  def execute(sql, name = nil); @would_execute_sql << sql << ";\n"; end
1127
1127
  end
1128
1128
  end
1129
1129
 
1130
1130
  after(:each) do
1131
- class <<@conn
1131
+ class << @conn
1132
1132
  remove_method :execute
1133
1133
  end
1134
1134
  @conn.instance_eval { remove_instance_variable :@would_execute_sql }