activerecord-oracle_enhanced-adapter 5.2.8 → 7.0.3

Sign up to get free protection for your applications and to get access to all the features.
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