activerecord-oracle_enhanced-adapter 5.2.8 → 7.0.3

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +390 -21
  3. data/README.md +35 -8
  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 +3 -3
  7. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +42 -37
  8. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +59 -60
  9. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +5 -10
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +86 -81
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +9 -10
  12. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +1 -2
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +37 -16
  14. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +1 -1
  15. data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +5 -6
  16. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +58 -49
  17. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +1 -1
  18. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +6 -7
  19. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +75 -51
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +13 -14
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +14 -4
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +27 -24
  23. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +156 -155
  24. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +103 -90
  25. data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +3 -2
  26. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +261 -161
  27. data/lib/active_record/type/oracle_enhanced/boolean.rb +0 -1
  28. data/lib/active_record/type/oracle_enhanced/character_string.rb +36 -0
  29. data/lib/active_record/type/oracle_enhanced/integer.rb +0 -1
  30. data/lib/arel/visitors/oracle.rb +221 -0
  31. data/lib/arel/visitors/oracle12.rb +128 -0
  32. data/spec/active_record/connection_adapters/emulation/oracle_adapter_spec.rb +0 -2
  33. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +78 -26
  34. data/spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb +7 -15
  35. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +5 -0
  36. data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +17 -17
  37. data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +7 -10
  38. data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +0 -15
  39. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +33 -36
  40. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +77 -258
  41. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +38 -39
  42. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +273 -85
  43. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +7 -8
  44. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +2 -4
  45. data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +43 -0
  46. data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
  47. data/spec/active_record/oracle_enhanced/type/decimal_spec.rb +56 -0
  48. data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +1 -1
  49. data/spec/active_record/oracle_enhanced/type/integer_spec.rb +2 -2
  50. data/spec/active_record/oracle_enhanced/type/json_spec.rb +0 -1
  51. data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +6 -5
  52. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +2 -4
  53. data/spec/spec_config.yaml.template +2 -2
  54. data/spec/spec_helper.rb +13 -2
  55. metadata +52 -30
  56. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +0 -28
@@ -7,29 +7,28 @@ module ActiveRecord
7
7
  # QUOTING ==================================================
8
8
  #
9
9
  # see: abstract/quoting.rb
10
+ QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
11
+ QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
10
12
 
11
- def quote_column_name(name) #:nodoc:
13
+ def quote_column_name(name) # :nodoc:
12
14
  name = name.to_s
13
- @quoted_column_names[name] ||= begin
14
- # if only valid lowercase column characters in name
15
- if name =~ /\A[a-z][a-z_0-9\$#]*\Z/
16
- "\"#{name.upcase}\""
17
- else
18
- # remove double quotes which cannot be used inside quoted identifier
19
- "\"#{name.gsub('"', '')}\""
20
- end
15
+ QUOTED_COLUMN_NAMES[name] ||= if /\A[a-z][a-z_0-9$#]*\Z/.match?(name)
16
+ "\"#{name.upcase}\""
17
+ else
18
+ # remove double quotes which cannot be used inside quoted identifier
19
+ "\"#{name.delete('"')}\""
21
20
  end
22
21
  end
23
22
 
24
23
  # This method is used in add_index to identify either column name (which is quoted)
25
24
  # or function based index (in which case function expression is not quoted)
26
- def quote_column_name_or_expression(name) #:nodoc:
25
+ def quote_column_name_or_expression(name) # :nodoc:
27
26
  name = name.to_s
28
27
  case name
29
28
  # if only valid lowercase column characters in name
30
- when /^[a-z][a-z_0-9\$#]*$/
29
+ when /^[a-z][a-z_0-9$#]*$/
31
30
  "\"#{name.upcase}\""
32
- when /^[a-z][a-z_0-9\$#\-]*$/i
31
+ when /^[a-z][a-z_0-9$#-]*$/i
33
32
  "\"#{name}\""
34
33
  # if other characters present then assume that it is expression
35
34
  # which should not be quoted
@@ -38,18 +37,6 @@ module ActiveRecord
38
37
  end
39
38
  end
40
39
 
41
- # Used only for quoting database links as the naming rules for links
42
- # differ from the rules for column names. Specifically, link names may
43
- # include periods.
44
- def quote_database_link(name)
45
- case name
46
- when NONQUOTED_DATABASE_LINK
47
- %Q("#{name.upcase}")
48
- else
49
- name
50
- end
51
- end
52
-
53
40
  # Names must be from 1 to 30 bytes long with these exceptions:
54
41
  # * Names of databases are limited to 8 bytes.
55
42
  # * Names of database links can be as long as 128 bytes.
@@ -61,18 +48,16 @@ module ActiveRecord
61
48
  #
62
49
  # Nonquoted identifiers can contain only alphanumeric characters from
63
50
  # your database character set and the underscore (_), dollar sign ($),
64
- # and pound sign (#). Database links can also contain periods (.) and
65
- # "at" signs (@). Oracle strongly discourages you from using $ and # in
66
- # nonquoted identifiers.
67
- NONQUOTED_OBJECT_NAME = /[[:alpha:]][\w$#]{0,29}/
68
- NONQUOTED_DATABASE_LINK = /[[:alpha:]][\w$#\.@]{0,127}/
69
- VALID_TABLE_NAME = /\A(?:#{NONQUOTED_OBJECT_NAME}\.)?#{NONQUOTED_OBJECT_NAME}(?:@#{NONQUOTED_DATABASE_LINK})?\Z/
51
+ # and pound sign (#).
52
+ # Oracle strongly discourages you from using $ and # in nonquoted identifiers.
53
+ NONQUOTED_OBJECT_NAME = /[[:alpha:]][\w$#]{0,29}/
54
+ VALID_TABLE_NAME = /\A(?:#{NONQUOTED_OBJECT_NAME}\.)?#{NONQUOTED_OBJECT_NAME}?\Z/
70
55
 
71
56
  # unescaped table name should start with letter and
72
57
  # contain letters, digits, _, $ or #
73
58
  # can be prefixed with schema name
74
59
  # CamelCase table names should be quoted
75
- def self.valid_table_name?(name) #:nodoc:
60
+ def self.valid_table_name?(name) # :nodoc:
76
61
  object_name = name.to_s
77
62
  !!(object_name =~ VALID_TABLE_NAME && !mixed_case?(object_name))
78
63
  end
@@ -82,19 +67,21 @@ module ActiveRecord
82
67
  !!(object_name =~ /[A-Z]/ && object_name =~ /[a-z]/)
83
68
  end
84
69
 
85
- def quote_table_name(name) #:nodoc:
86
- name, link = name.to_s.split("@")
87
- @quoted_table_names[name] ||= [name.split(".").map { |n| quote_column_name(n) }.join("."), quote_database_link(link)].compact.join("@")
70
+ def quote_table_name(name) # :nodoc:
71
+ name, _link = name.to_s.split("@")
72
+ QUOTED_TABLE_NAMES[name] ||= [name.split(".").map { |n| quote_column_name(n) }].join(".")
88
73
  end
89
74
 
90
- def quote_string(s) #:nodoc:
75
+ def quote_string(s) # :nodoc:
91
76
  s.gsub(/'/, "''")
92
77
  end
93
78
 
94
- def _quote(value) #:nodoc:
79
+ def quote(value) # :nodoc:
95
80
  case value
81
+ when Type::OracleEnhanced::CharacterString::Data then
82
+ "'#{quote_string(value.to_s)}'"
96
83
  when Type::OracleEnhanced::NationalCharacterString::Data then
97
- "N".dup << "'#{quote_string(value.to_s)}'"
84
+ +"N" << "'#{quote_string(value.to_s)}'"
98
85
  when ActiveModel::Type::Binary::Data then
99
86
  "empty_blob()"
100
87
  when Type::OracleEnhanced::Text::Data then
@@ -106,55 +93,92 @@ module ActiveRecord
106
93
  end
107
94
  end
108
95
 
109
- def quoted_true #:nodoc:
96
+ def quoted_true # :nodoc:
110
97
  return "'Y'" if emulate_booleans_from_strings
111
- "1".freeze
98
+ "1"
112
99
  end
113
100
 
114
- def unquoted_true #:nodoc:
101
+ def unquoted_true # :nodoc:
115
102
  return "Y" if emulate_booleans_from_strings
116
- "1".freeze
103
+ "1"
117
104
  end
118
105
 
119
- def quoted_false #:nodoc:
106
+ def quoted_false # :nodoc:
120
107
  return "'N'" if emulate_booleans_from_strings
121
- "0".freeze
108
+ "0"
122
109
  end
123
110
 
124
- def unquoted_false #:nodoc:
111
+ def unquoted_false # :nodoc:
125
112
  return "N" if emulate_booleans_from_strings
126
- "0".freeze
113
+ "0"
127
114
  end
128
115
 
129
- def _type_cast(value)
116
+ def type_cast(value)
130
117
  case value
131
118
  when Type::OracleEnhanced::TimestampTz::Data, Type::OracleEnhanced::TimestampLtz::Data
132
119
  if value.acts_like?(:time)
133
- zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
120
+ zone_conversion_method = ActiveRecord.default_timezone == :utc ? :getutc : :getlocal
134
121
  value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
135
122
  else
136
123
  value
137
124
  end
138
125
  when Type::OracleEnhanced::NationalCharacterString::Data
139
126
  value.to_s
127
+ when Type::OracleEnhanced::CharacterString::Data
128
+ value
140
129
  else
141
130
  super
142
131
  end
143
132
  end
144
133
 
145
- private
134
+ def column_name_matcher
135
+ COLUMN_NAME
136
+ end
146
137
 
138
+ def column_name_with_order_matcher
139
+ COLUMN_NAME_WITH_ORDER
140
+ end
141
+
142
+ COLUMN_NAME = /
143
+ \A
144
+ (
145
+ (?:
146
+ # "table_name"."column_name" | function(one or no argument)
147
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
148
+ )
149
+ (?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
150
+ )
151
+ (?:\s*,\s*\g<1>)*
152
+ \z
153
+ /ix
154
+
155
+ COLUMN_NAME_WITH_ORDER = /
156
+ \A
157
+ (
158
+ (?:
159
+ # "table_name"."column_name" | function(one or no argument)
160
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
161
+ )
162
+ (?:\s+ASC|\s+DESC)?
163
+ (?:\s+NULLS\s+(?:FIRST|LAST))?
164
+ )
165
+ (?:\s*,\s*\g<1>)*
166
+ \z
167
+ /ix
168
+ private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
169
+
170
+ private
147
171
  def oracle_downcase(column_name)
148
172
  return nil if column_name.nil?
149
- column_name =~ /[a-z]/ ? column_name : column_name.downcase
173
+ /[a-z]/.match?(column_name) ? column_name : column_name.downcase
150
174
  end
151
175
  end
152
176
  end
153
177
  end
154
178
  end
155
179
 
156
- # if MRI or YARV
157
- if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
180
+ # if MRI or YARV or TruffleRuby
181
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" || RUBY_ENGINE == "truffleruby"
158
182
  require "active_record/connection_adapters/oracle_enhanced/oci_quoting"
159
183
  # if JRuby
160
184
  elsif RUBY_ENGINE == "jruby"
@@ -3,11 +3,10 @@
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module OracleEnhanced
6
- class SchemaCreation < AbstractAdapter::SchemaCreation
6
+ class SchemaCreation < SchemaCreation
7
7
  private
8
-
9
8
  def visit_ColumnDefinition(o)
10
- if [:blob, :clob, :nclob].include?(sql_type = type_to_sql(o.type, o.options).downcase.to_sym)
9
+ if [:blob, :clob, :nclob].include?(sql_type = type_to_sql(o.type, **o.options).downcase.to_sym)
11
10
  if (tablespace = default_tablespace_for(sql_type))
12
11
  @lob_tablespaces ||= {}
13
12
  @lob_tablespaces[o.name] = tablespace
@@ -17,12 +16,12 @@ module ActiveRecord
17
16
  end
18
17
 
19
18
  def visit_TableDefinition(o)
20
- create_sql = "CREATE#{' GLOBAL TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} ".dup
19
+ create_sql = +"CREATE#{' GLOBAL TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} "
21
20
  statements = o.columns.map { |c| accept c }
22
21
  statements << accept(o.primary_keys) if o.primary_keys
23
22
 
24
- if supports_foreign_keys_in_create?
25
- statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
23
+ if supports_foreign_keys?
24
+ statements.concat(o.foreign_keys.map { |fk| accept fk })
26
25
  end
27
26
 
28
27
  create_sql << "(#{statements.join(', ')})" if statements.present?
@@ -36,7 +35,7 @@ module ActiveRecord
36
35
  create_sql << " TABLESPACE #{tablespace}"
37
36
  end
38
37
  end
39
- add_table_options!(create_sql, table_options(o))
38
+ add_table_options!(create_sql, o)
40
39
  create_sql << " AS #{to_sql(o.as)}" if o.as
41
40
  create_sql
42
41
  end
@@ -75,18 +74,18 @@ module ActiveRecord
75
74
 
76
75
  def action_sql(action, dependency)
77
76
  if action == "UPDATE"
78
- raise ArgumentError, <<-MSG.strip_heredoc
79
- '#{action}' is not supported by Oracle
80
- MSG
77
+ raise ArgumentError, <<~MSG
78
+ '#{action}' is not supported by Oracle
79
+ MSG
81
80
  end
82
81
  case dependency
83
82
  when :nullify then "ON #{action} SET NULL"
84
83
  when :cascade then "ON #{action} CASCADE"
85
84
  else
86
- raise ArgumentError, <<-MSG.strip_heredoc
87
- '#{dependency}' is not supported for #{action}
88
- Supported values are: :nullify, :cascade
89
- MSG
85
+ raise ArgumentError, <<~MSG
86
+ '#{dependency}' is not supported for #{action}
87
+ Supported values are: :nullify, :cascade
88
+ MSG
90
89
  end
91
90
  end
92
91
  end
@@ -17,7 +17,7 @@ module ActiveRecord
17
17
  ].each do |column_type|
18
18
  module_eval <<-CODE, __FILE__, __LINE__ + 1
19
19
  def #{column_type}(*args, **options)
20
- args.each { |name| column(name, :#{column_type}, options) }
20
+ args.each { |name| column(name, :#{column_type}, **options) }
21
21
  end
22
22
  CODE
23
23
  end
@@ -35,7 +35,7 @@ module ActiveRecord
35
35
  end
36
36
  end
37
37
 
38
- class SynonymDefinition < Struct.new(:name, :table_owner, :table_name, :db_link) #:nodoc:
38
+ class SynonymDefinition < Struct.new(:name, :table_owner, :table_name) # :nodoc:
39
39
  end
40
40
 
41
41
  class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition
@@ -53,10 +53,20 @@ module ActiveRecord
53
53
  include OracleEnhanced::ColumnMethods
54
54
 
55
55
  attr_accessor :tablespace, :organization
56
- def initialize(name, temporary = false, options = nil, as = nil, tablespace = nil, organization = nil, comment: nil)
56
+ def initialize(
57
+ conn,
58
+ name,
59
+ temporary: false,
60
+ options: nil,
61
+ as: nil,
62
+ tablespace: nil,
63
+ organization: nil,
64
+ comment: nil,
65
+ **
66
+ )
57
67
  @tablespace = tablespace
58
68
  @organization = organization
59
- super(name, temporary, options, as, comment: comment)
69
+ super(conn, name, temporary: temporary, options: options, as: as, comment: comment)
60
70
  end
61
71
 
62
72
  def new_column_definition(name, type, **options) # :nodoc:
@@ -1,10 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActiveRecord #:nodoc:
4
- module ConnectionAdapters #:nodoc:
5
- module OracleEnhanced #:nodoc:
6
- class SchemaDumper < ConnectionAdapters::SchemaDumper #:nodoc:
3
+ module ActiveRecord # :nodoc:
4
+ module ConnectionAdapters # :nodoc:
5
+ module OracleEnhanced # :nodoc:
6
+ class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
7
+ DEFAULT_PRIMARY_KEY_COLUMN_SPEC = { precision: "38", null: "false" }.freeze
8
+ private_constant :DEFAULT_PRIMARY_KEY_COLUMN_SPEC
9
+
7
10
  private
11
+ def column_spec_for_primary_key(column)
12
+ spec = super
13
+ spec.except!(:precision) if prepare_column_options(column) == DEFAULT_PRIMARY_KEY_COLUMN_SPEC
14
+ spec
15
+ end
8
16
 
9
17
  def tables(stream)
10
18
  # do not include materialized views in schema dump - they should be created separately after schema creation
@@ -13,8 +21,6 @@ module ActiveRecord #:nodoc:
13
21
  # add table prefix or suffix for schema_migrations
14
22
  next if ignored? tbl
15
23
  table(tbl, stream)
16
- # add primary key trigger if table has it
17
- primary_key_trigger(tbl, stream)
18
24
  end
19
25
  # following table definitions
20
26
  # add foreign keys if table has them
@@ -27,22 +33,12 @@ module ActiveRecord #:nodoc:
27
33
  synonyms(stream)
28
34
  end
29
35
 
30
- def primary_key_trigger(table_name, stream)
31
- if @connection.has_primary_key_trigger?(table_name)
32
- pk, _pk_seq = @connection.pk_and_sequence_for(table_name)
33
- stream.print " add_primary_key_trigger #{table_name.inspect}"
34
- stream.print ", primary_key: \"#{pk}\"" if pk != "id"
35
- stream.print "\n\n"
36
- end
37
- end
38
-
39
36
  def synonyms(stream)
40
37
  syns = @connection.synonyms
41
38
  syns.each do |syn|
42
39
  next if ignored? syn.name
43
40
  table_name = syn.table_name
44
41
  table_name = "#{syn.table_owner}.#{table_name}" if syn.table_owner
45
- table_name = "#{table_name}@#{syn.db_link}" if syn.db_link
46
42
  stream.print " add_synonym #{syn.name.inspect}, #{table_name.inspect}, force: true"
47
43
  stream.puts
48
44
  end
@@ -51,7 +47,7 @@ module ActiveRecord #:nodoc:
51
47
 
52
48
  def _indexes(table, stream)
53
49
  if (indexes = @connection.indexes(table)).any?
54
- add_index_statements = indexes.map do |index|
50
+ add_index_statements = indexes.filter_map do |index|
55
51
  case index.type
56
52
  when nil
57
53
  # do nothing here. see indexes_in_create
@@ -63,6 +59,7 @@ module ActiveRecord #:nodoc:
63
59
  else
64
60
  statement_parts = [ ("add_context_index " + remove_prefix_and_suffix(table).inspect) ]
65
61
  statement_parts << index.columns.inspect
62
+ statement_parts << ("sync: " + $1.inspect) if index.parameters =~ /SYNC\((.*?)\)/
66
63
  statement_parts << ("name: " + index.name.inspect)
67
64
  end
68
65
  else
@@ -70,7 +67,7 @@ module ActiveRecord #:nodoc:
70
67
  statement_parts = ["# unrecognized index #{index.name.inspect} with type #{index.type.inspect}"]
71
68
  end
72
69
  " " + statement_parts.join(", ") unless statement_parts.empty?
73
- end.compact
70
+ end
74
71
 
75
72
  return if add_index_statements.empty?
76
73
 
@@ -84,7 +81,7 @@ module ActiveRecord #:nodoc:
84
81
  index_statements = indexes.map do |index|
85
82
  " t.index #{index_parts(index).join(', ')}" unless index.type == "CTXSYS.CONTEXT"
86
83
  end
87
- stream.puts index_statements.sort.join("\n")
84
+ stream.puts index_statements.compact.sort.join("\n")
88
85
  end
89
86
  end
90
87
 
@@ -97,6 +94,8 @@ module ActiveRecord #:nodoc:
97
94
  def table(table, stream)
98
95
  columns = @connection.columns(table)
99
96
  begin
97
+ self.table_name = table
98
+
100
99
  tbl = StringIO.new
101
100
 
102
101
  # first dump primary key column
@@ -117,7 +116,10 @@ module ActiveRecord #:nodoc:
117
116
  tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
118
117
  pkcol = columns.detect { |c| c.name == pk }
119
118
  pkcolspec = column_spec_for_primary_key(pkcol)
120
- if pkcolspec.present?
119
+ unless pkcolspec.empty?
120
+ if pkcolspec != pkcolspec.slice(:id, :default)
121
+ pkcolspec = { id: { type: pkcolspec.delete(:id), **pkcolspec }.compact }
122
+ end
121
123
  tbl.print ", #{format_colspec(pkcolspec)}"
122
124
  end
123
125
  when Array
@@ -156,6 +158,8 @@ module ActiveRecord #:nodoc:
156
158
  stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
157
159
  stream.puts "# #{e.message}"
158
160
  stream.puts
161
+ ensure
162
+ self.table_name = nil
159
163
  end
160
164
  end
161
165
 
@@ -176,10 +180,9 @@ module ActiveRecord #:nodoc:
176
180
 
177
181
  def extract_expression_for_virtual_column(column)
178
182
  column_name = column.name
179
- table_name = column.table_name
180
- @connection.select_value(<<-SQL.strip.gsub(/\s+/, " "), "Table comment", [bind_string("table_name", table_name.upcase), bind_string("column_name", column_name.upcase)]).inspect
181
- select data_default from all_tab_columns
182
- where owner = SYS_CONTEXT('userenv', 'session_user')
183
+ @connection.select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase), bind_string("column_name", column_name.upcase)]).inspect
184
+ select /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ data_default from all_tab_columns
185
+ where owner = SYS_CONTEXT('userenv', 'current_schema')
183
186
  and table_name = :table_name
184
187
  and column_name = :column_name
185
188
  SQL