Skip to content

Commit f185e0e

Browse files
committed
Except table_name from column objects
The `table_name` was added at rails#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.
1 parent bf1494a commit f185e0e

File tree

7 files changed

+48
-49
lines changed

7 files changed

+48
-49
lines changed

activerecord/lib/active_record/connection_adapters/column.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module ActiveRecord
55
module ConnectionAdapters
66
# An abstract definition of a column in a table.
77
class Column
8-
attr_reader :name, :default, :sql_type_metadata, :null, :table_name, :default_function, :collation, :comment
8+
attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment
99

1010
delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
1111

@@ -15,9 +15,8 @@ class Column
1515
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
1616
# +sql_type_metadata+ is various information about the type of the column
1717
# +null+ determines if this column allows +NULL+ values.
18-
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil, **)
18+
def initialize(name, default, sql_type_metadata = nil, null = true, default_function = nil, collation: nil, comment: nil, **)
1919
@name = name.freeze
20-
@table_name = table_name
2120
@sql_type_metadata = sql_type_metadata
2221
@null = null
2322
@default = default
@@ -44,7 +43,6 @@ def human_name
4443

4544
def init_with(coder)
4645
@name = coder["name"]
47-
@table_name = coder["table_name"]
4846
@sql_type_metadata = coder["sql_type_metadata"]
4947
@null = coder["null"]
5048
@default = coder["default"]
@@ -55,7 +53,6 @@ def init_with(coder)
5553

5654
def encode_with(coder)
5755
coder["name"] = @name
58-
coder["table_name"] = @table_name
5956
coder["sql_type_metadata"] = @sql_type_metadata
6057
coder["null"] = @null
6158
coder["default"] = @default
@@ -77,7 +74,7 @@ def hash
7774
protected
7875

7976
def attributes_for_hash
80-
[self.class, name, default, sql_type_metadata, null, table_name, default_function, collation]
77+
[self.class, name, default, sql_type_metadata, null, default_function, collation, comment]
8178
end
8279
end
8380

activerecord/lib/active_record/connection_adapters/mysql/schema_dumper.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def schema_precision(column)
5555
end
5656

5757
def schema_collation(column)
58-
if column.collation && table_name = column.table_name
58+
if column.collation
5959
@table_collation_cache ||= {}
6060
@table_collation_cache[table_name] ||=
6161
@connection.exec_query("SHOW TABLE STATUS LIKE #{@connection.quote(table_name)}", "SCHEMA").first["Collation"]
@@ -65,13 +65,13 @@ def schema_collation(column)
6565

6666
def extract_expression_for_virtual_column(column)
6767
if @connection.mariadb? && @connection.database_version < "10.2.5"
68-
create_table_info = @connection.send(:create_table_info, column.table_name)
68+
create_table_info = @connection.send(:create_table_info, table_name)
6969
column_name = @connection.quote_column_name(column.name)
7070
if %r/#{column_name} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
7171
$~[:expression].inspect
7272
end
7373
else
74-
scope = @connection.send(:quoted_scope, column.table_name)
74+
scope = @connection.send(:quoted_scope, table_name)
7575
column_name = @connection.quote(column.name)
7676
sql = "SELECT generation_expression FROM information_schema.columns" \
7777
" WHERE table_schema = #{scope[:schema]}" \

activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,8 @@ def new_column_from_field(table_name, field)
174174
default,
175175
type_metadata,
176176
field[:Null] == "YES",
177-
table_name,
178177
default_function,
179-
field[:Collation],
178+
collation: field[:Collation],
180179
comment: field[:Comment].presence
181180
)
182181
end

activerecord/lib/active_record/connection_adapters/postgresql/column.rb

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,21 @@
22

33
module ActiveRecord
44
module ConnectionAdapters
5-
# PostgreSQL-specific extensions to column definitions in a table.
6-
class PostgreSQLColumn < Column #:nodoc:
7-
delegate :array, :oid, :fmod, to: :sql_type_metadata
8-
alias :array? :array
9-
10-
def initialize(*, max_identifier_length: 63, **)
11-
super
12-
@max_identifier_length = max_identifier_length
13-
end
14-
15-
def serial?
16-
return unless default_function
17-
18-
if %r{\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z} =~ default_function
19-
sequence_name_from_parts(table_name, name, suffix) == sequence_name
5+
module PostgreSQL
6+
class Column < ConnectionAdapters::Column # :nodoc:
7+
delegate :array, :oid, :fmod, to: :sql_type_metadata
8+
alias :array? :array
9+
10+
def initialize(*, serial: nil, **)
11+
super
12+
@serial = serial
2013
end
21-
end
2214

23-
private
24-
attr_reader :max_identifier_length
25-
26-
def sequence_name_from_parts(table_name, column_name, suffix)
27-
over_length = [table_name, column_name, suffix].map(&:length).sum + 2 - max_identifier_length
28-
29-
if over_length > 0
30-
column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
31-
over_length -= column_name.length - column_name_length
32-
column_name = column_name[0, column_name_length - [over_length, 0].min]
33-
end
34-
35-
if over_length > 0
36-
table_name = table_name[0, table_name.length - over_length]
37-
end
38-
39-
"#{table_name}_#{column_name}_#{suffix}"
15+
def serial?
16+
@serial
4017
end
18+
end
4119
end
20+
PostgreSQLColumn = PostgreSQL::Column # :nodoc:
4221
end
4322
end

activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -650,16 +650,19 @@ def new_column_from_field(table_name, field)
650650
default_value = extract_value_from_default(default)
651651
default_function = extract_default_function(default_value, default)
652652

653-
PostgreSQLColumn.new(
653+
if match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/)
654+
serial = sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
655+
end
656+
657+
PostgreSQL::Column.new(
654658
column_name,
655659
default_value,
656660
type_metadata,
657661
!notnull,
658-
table_name,
659662
default_function,
660-
collation,
663+
collation: collation,
661664
comment: comment.presence,
662-
max_identifier_length: max_identifier_length
665+
serial: serial
663666
)
664667
end
665668

@@ -675,6 +678,22 @@ def fetch_type_metadata(column_name, sql_type, oid, fmod)
675678
PostgreSQLTypeMetadata.new(simple_type, oid: oid, fmod: fmod)
676679
end
677680

681+
def sequence_name_from_parts(table_name, column_name, suffix)
682+
over_length = [table_name, column_name, suffix].sum(&:length) + 2 - max_identifier_length
683+
684+
if over_length > 0
685+
column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
686+
over_length -= column_name.length - column_name_length
687+
column_name = column_name[0, column_name_length - [over_length, 0].min]
688+
end
689+
690+
if over_length > 0
691+
table_name = table_name[0, table_name.length - over_length]
692+
end
693+
694+
"#{table_name}_#{column_name}_#{suffix}"
695+
end
696+
678697
def extract_foreign_key_action(specifier)
679698
case specifier
680699
when "c"; :cascade

activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def new_column_from_field(table_name, field)
105105
end
106106

107107
type_metadata = fetch_type_metadata(field["type"])
108-
Column.new(field["name"], default, type_metadata, field["notnull"].to_i == 0, table_name, nil, field["collation"])
108+
Column.new(field["name"], default, type_metadata, field["notnull"].to_i == 0, collation: field["collation"])
109109
end
110110

111111
def data_source_sql(name = nil, type: nil)

activerecord/lib/active_record/schema_dumper.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def dump(stream)
4747
end
4848

4949
private
50+
attr_accessor :table_name
5051

5152
def initialize(connection, options = {})
5253
@connection = connection
@@ -110,6 +111,8 @@ def tables(stream)
110111
def table(table, stream)
111112
columns = @connection.columns(table)
112113
begin
114+
self.table_name = table
115+
113116
tbl = StringIO.new
114117

115118
# first dump primary key column
@@ -159,6 +162,8 @@ def table(table, stream)
159162
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
160163
stream.puts "# #{e.message}"
161164
stream.puts
165+
ensure
166+
self.table_name = nil
162167
end
163168
end
164169

0 commit comments

Comments
 (0)