mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Except table_name
from column objects
The `table_name` was added at #23677 to detect whether serial column or not correctly. We can do that detection before initialize column object, it makes column object size smaller, and it probably helps column object de-duplication.
This commit is contained in:
parent
bf1494a101
commit
f185e0ebc9
7 changed files with 47 additions and 48 deletions
|
@ -5,7 +5,7 @@ module ActiveRecord
|
|||
module ConnectionAdapters
|
||||
# An abstract definition of a column in a table.
|
||||
class Column
|
||||
attr_reader :name, :default, :sql_type_metadata, :null, :table_name, :default_function, :collation, :comment
|
||||
attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment
|
||||
|
||||
delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
|
||||
|
||||
|
@ -15,9 +15,8 @@ module ActiveRecord
|
|||
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
||||
# +sql_type_metadata+ is various information about the type of the column
|
||||
# +null+ determines if this column allows +NULL+ values.
|
||||
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil, **)
|
||||
def initialize(name, default, sql_type_metadata = nil, null = true, default_function = nil, collation: nil, comment: nil, **)
|
||||
@name = name.freeze
|
||||
@table_name = table_name
|
||||
@sql_type_metadata = sql_type_metadata
|
||||
@null = null
|
||||
@default = default
|
||||
|
@ -44,7 +43,6 @@ module ActiveRecord
|
|||
|
||||
def init_with(coder)
|
||||
@name = coder["name"]
|
||||
@table_name = coder["table_name"]
|
||||
@sql_type_metadata = coder["sql_type_metadata"]
|
||||
@null = coder["null"]
|
||||
@default = coder["default"]
|
||||
|
@ -55,7 +53,6 @@ module ActiveRecord
|
|||
|
||||
def encode_with(coder)
|
||||
coder["name"] = @name
|
||||
coder["table_name"] = @table_name
|
||||
coder["sql_type_metadata"] = @sql_type_metadata
|
||||
coder["null"] = @null
|
||||
coder["default"] = @default
|
||||
|
@ -77,7 +74,7 @@ module ActiveRecord
|
|||
protected
|
||||
|
||||
def attributes_for_hash
|
||||
[self.class, name, default, sql_type_metadata, null, table_name, default_function, collation]
|
||||
[self.class, name, default, sql_type_metadata, null, default_function, collation, comment]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def schema_collation(column)
|
||||
if column.collation && table_name = column.table_name
|
||||
if column.collation
|
||||
@table_collation_cache ||= {}
|
||||
@table_collation_cache[table_name] ||=
|
||||
@connection.exec_query("SHOW TABLE STATUS LIKE #{@connection.quote(table_name)}", "SCHEMA").first["Collation"]
|
||||
|
@ -65,13 +65,13 @@ module ActiveRecord
|
|||
|
||||
def extract_expression_for_virtual_column(column)
|
||||
if @connection.mariadb? && @connection.database_version < "10.2.5"
|
||||
create_table_info = @connection.send(:create_table_info, column.table_name)
|
||||
create_table_info = @connection.send(:create_table_info, table_name)
|
||||
column_name = @connection.quote_column_name(column.name)
|
||||
if %r/#{column_name} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
|
||||
$~[:expression].inspect
|
||||
end
|
||||
else
|
||||
scope = @connection.send(:quoted_scope, column.table_name)
|
||||
scope = @connection.send(:quoted_scope, table_name)
|
||||
column_name = @connection.quote(column.name)
|
||||
sql = "SELECT generation_expression FROM information_schema.columns" \
|
||||
" WHERE table_schema = #{scope[:schema]}" \
|
||||
|
|
|
@ -174,9 +174,8 @@ module ActiveRecord
|
|||
default,
|
||||
type_metadata,
|
||||
field[:Null] == "YES",
|
||||
table_name,
|
||||
default_function,
|
||||
field[:Collation],
|
||||
collation: field[:Collation],
|
||||
comment: field[:Comment].presence
|
||||
)
|
||||
end
|
||||
|
|
|
@ -2,42 +2,21 @@
|
|||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
# PostgreSQL-specific extensions to column definitions in a table.
|
||||
class PostgreSQLColumn < Column #:nodoc:
|
||||
delegate :array, :oid, :fmod, to: :sql_type_metadata
|
||||
alias :array? :array
|
||||
module PostgreSQL
|
||||
class Column < ConnectionAdapters::Column # :nodoc:
|
||||
delegate :array, :oid, :fmod, to: :sql_type_metadata
|
||||
alias :array? :array
|
||||
|
||||
def initialize(*, max_identifier_length: 63, **)
|
||||
super
|
||||
@max_identifier_length = max_identifier_length
|
||||
end
|
||||
def initialize(*, serial: nil, **)
|
||||
super
|
||||
@serial = serial
|
||||
end
|
||||
|
||||
def serial?
|
||||
return unless default_function
|
||||
|
||||
if %r{\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z} =~ default_function
|
||||
sequence_name_from_parts(table_name, name, suffix) == sequence_name
|
||||
def serial?
|
||||
@serial
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :max_identifier_length
|
||||
|
||||
def sequence_name_from_parts(table_name, column_name, suffix)
|
||||
over_length = [table_name, column_name, suffix].map(&:length).sum + 2 - max_identifier_length
|
||||
|
||||
if over_length > 0
|
||||
column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
|
||||
over_length -= column_name.length - column_name_length
|
||||
column_name = column_name[0, column_name_length - [over_length, 0].min]
|
||||
end
|
||||
|
||||
if over_length > 0
|
||||
table_name = table_name[0, table_name.length - over_length]
|
||||
end
|
||||
|
||||
"#{table_name}_#{column_name}_#{suffix}"
|
||||
end
|
||||
end
|
||||
PostgreSQLColumn = PostgreSQL::Column # :nodoc:
|
||||
end
|
||||
end
|
||||
|
|
|
@ -650,16 +650,19 @@ module ActiveRecord
|
|||
default_value = extract_value_from_default(default)
|
||||
default_function = extract_default_function(default_value, default)
|
||||
|
||||
PostgreSQLColumn.new(
|
||||
if match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/)
|
||||
serial = sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
|
||||
end
|
||||
|
||||
PostgreSQL::Column.new(
|
||||
column_name,
|
||||
default_value,
|
||||
type_metadata,
|
||||
!notnull,
|
||||
table_name,
|
||||
default_function,
|
||||
collation,
|
||||
collation: collation,
|
||||
comment: comment.presence,
|
||||
max_identifier_length: max_identifier_length
|
||||
serial: serial
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -675,6 +678,22 @@ module ActiveRecord
|
|||
PostgreSQLTypeMetadata.new(simple_type, oid: oid, fmod: fmod)
|
||||
end
|
||||
|
||||
def sequence_name_from_parts(table_name, column_name, suffix)
|
||||
over_length = [table_name, column_name, suffix].sum(&:length) + 2 - max_identifier_length
|
||||
|
||||
if over_length > 0
|
||||
column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
|
||||
over_length -= column_name.length - column_name_length
|
||||
column_name = column_name[0, column_name_length - [over_length, 0].min]
|
||||
end
|
||||
|
||||
if over_length > 0
|
||||
table_name = table_name[0, table_name.length - over_length]
|
||||
end
|
||||
|
||||
"#{table_name}_#{column_name}_#{suffix}"
|
||||
end
|
||||
|
||||
def extract_foreign_key_action(specifier)
|
||||
case specifier
|
||||
when "c"; :cascade
|
||||
|
|
|
@ -105,7 +105,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
type_metadata = fetch_type_metadata(field["type"])
|
||||
Column.new(field["name"], default, type_metadata, field["notnull"].to_i == 0, table_name, nil, field["collation"])
|
||||
Column.new(field["name"], default, type_metadata, field["notnull"].to_i == 0, collation: field["collation"])
|
||||
end
|
||||
|
||||
def data_source_sql(name = nil, type: nil)
|
||||
|
|
|
@ -47,6 +47,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
private
|
||||
attr_accessor :table_name
|
||||
|
||||
def initialize(connection, options = {})
|
||||
@connection = connection
|
||||
|
@ -110,6 +111,8 @@ HEADER
|
|||
def table(table, stream)
|
||||
columns = @connection.columns(table)
|
||||
begin
|
||||
self.table_name = table
|
||||
|
||||
tbl = StringIO.new
|
||||
|
||||
# first dump primary key column
|
||||
|
@ -159,6 +162,8 @@ HEADER
|
|||
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
||||
stream.puts "# #{e.message}"
|
||||
stream.puts
|
||||
ensure
|
||||
self.table_name = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue