activerecord-oracle_enhanced-adapter 6.1.6 → 7.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +53 -2
  3. data/README.md +1 -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 +16 -17
  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 +12 -6
  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 +35 -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 +124 -99
  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/timestamp_spec.rb +2 -2
  37. metadata +5 -5
@@ -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
@@ -661,11 +662,11 @@ module ActiveRecord
661
662
  }.reject(&:blank?).map.with_index { |column, i|
662
663
  "FIRST_VALUE(#{column}) OVER (PARTITION BY #{columns} ORDER BY #{column}) AS alias_#{i}__"
663
664
  }
664
- (order_columns << super).join(", ")
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 }