activerecord 6.0.0.beta1 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +455 -9
- data/README.rdoc +3 -1
- data/lib/active_record/associations/association.rb +18 -1
- data/lib/active_record/associations/builder/association.rb +14 -18
- data/lib/active_record/associations/builder/belongs_to.rb +5 -2
- data/lib/active_record/associations/builder/collection_association.rb +5 -15
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +35 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +5 -6
- data/lib/active_record/associations/collection_proxy.rb +13 -42
- data/lib/active_record/associations/has_many_association.rb +1 -9
- data/lib/active_record/associations/has_many_through_association.rb +4 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +21 -7
- data/lib/active_record/associations/join_dependency.rb +10 -9
- data/lib/active_record/associations/preloader/association.rb +37 -34
- data/lib/active_record/associations/preloader/through_association.rb +48 -39
- data/lib/active_record/associations/preloader.rb +11 -6
- data/lib/active_record/associations.rb +3 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
- data/lib/active_record/attribute_methods/dirty.rb +47 -14
- data/lib/active_record/attribute_methods/primary_key.rb +7 -15
- data/lib/active_record/attribute_methods/query.rb +2 -3
- data/lib/active_record/attribute_methods/read.rb +3 -9
- data/lib/active_record/attribute_methods/write.rb +6 -12
- data/lib/active_record/attribute_methods.rb +3 -53
- data/lib/active_record/attributes.rb +13 -0
- data/lib/active_record/autosave_association.rb +15 -5
- data/lib/active_record/base.rb +0 -1
- data/lib/active_record/callbacks.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +124 -23
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +8 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +101 -70
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +11 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +63 -6
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +51 -40
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +95 -30
- data/lib/active_record/connection_adapters/abstract/transaction.rb +17 -6
- data/lib/active_record/connection_adapters/abstract_adapter.rb +108 -39
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +93 -134
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +1 -1
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +3 -3
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +66 -5
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +18 -5
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -30
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -3
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +98 -89
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +47 -63
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +23 -27
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +91 -24
- data/lib/active_record/connection_adapters/schema_cache.rb +32 -14
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +28 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +69 -118
- data/lib/active_record/connection_handling.rb +32 -16
- data/lib/active_record/core.rb +27 -20
- data/lib/active_record/database_configurations/hash_config.rb +11 -11
- data/lib/active_record/database_configurations/url_config.rb +21 -16
- data/lib/active_record/database_configurations.rb +99 -50
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/enum.rb +15 -0
- data/lib/active_record/errors.rb +18 -13
- data/lib/active_record/fixtures.rb +11 -6
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +13 -1
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +3 -4
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +28 -14
- data/lib/active_record/migration/compatibility.rb +72 -63
- data/lib/active_record/migration.rb +62 -44
- data/lib/active_record/persistence.rb +212 -19
- data/lib/active_record/querying.rb +18 -14
- data/lib/active_record/railtie.rb +9 -1
- data/lib/active_record/railties/collection_cache_association_loading.rb +3 -3
- data/lib/active_record/railties/databases.rake +124 -25
- data/lib/active_record/reflection.rb +18 -32
- data/lib/active_record/relation/calculations.rb +40 -44
- data/lib/active_record/relation/delegation.rb +23 -31
- data/lib/active_record/relation/finder_methods.rb +13 -13
- data/lib/active_record/relation/merger.rb +11 -16
- data/lib/active_record/relation/query_attribute.rb +5 -3
- data/lib/active_record/relation/query_methods.rb +217 -68
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +10 -10
- data/lib/active_record/relation.rb +184 -35
- data/lib/active_record/sanitization.rb +33 -4
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +10 -1
- data/lib/active_record/schema_migration.rb +1 -1
- data/lib/active_record/scoping/default.rb +7 -15
- data/lib/active_record/scoping/named.rb +10 -2
- data/lib/active_record/scoping.rb +6 -7
- data/lib/active_record/statement_cache.rb +2 -2
- data/lib/active_record/store.rb +48 -0
- data/lib/active_record/table_metadata.rb +9 -13
- data/lib/active_record/tasks/database_tasks.rb +109 -6
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -1
- data/lib/active_record/test_databases.rb +1 -16
- data/lib/active_record/test_fixtures.rb +2 -2
- data/lib/active_record/timestamp.rb +35 -19
- data/lib/active_record/touch_later.rb +4 -2
- data/lib/active_record/transactions.rb +55 -45
- data/lib/active_record/type_caster/connection.rb +16 -10
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record.rb +7 -1
- data/lib/arel/insert_manager.rb +3 -3
- data/lib/arel/nodes/and.rb +1 -1
- data/lib/arel/nodes/case.rb +1 -1
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/select_core.rb +16 -12
- data/lib/arel/nodes/unary.rb +1 -0
- data/lib/arel/nodes/values_list.rb +2 -17
- data/lib/arel/nodes.rb +2 -1
- data/lib/arel/select_manager.rb +10 -10
- data/lib/arel/visitors/depth_first.rb +7 -2
- data/lib/arel/visitors/dot.rb +7 -2
- data/lib/arel/visitors/ibm_db.rb +13 -0
- data/lib/arel/visitors/informix.rb +6 -0
- data/lib/arel/visitors/mssql.rb +15 -1
- data/lib/arel/visitors/oracle12.rb +4 -5
- data/lib/arel/visitors/postgresql.rb +4 -10
- data/lib/arel/visitors/to_sql.rb +107 -131
- data/lib/arel/visitors/visitor.rb +9 -5
- data/lib/arel.rb +7 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +17 -13
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/arel/nodes/values.rb +0 -16
@@ -110,7 +110,7 @@ module ActiveRecord
|
|
110
110
|
end
|
111
111
|
alias :exec_update :exec_delete
|
112
112
|
|
113
|
-
def sql_for_insert(sql, pk,
|
113
|
+
def sql_for_insert(sql, pk, binds) # :nodoc:
|
114
114
|
if pk.nil?
|
115
115
|
# Extract the table from the insert sql. Yuck.
|
116
116
|
table_ref = extract_table_ref_from_insert_sql(sql)
|
@@ -164,6 +164,10 @@ module ActiveRecord
|
|
164
164
|
end
|
165
165
|
|
166
166
|
private
|
167
|
+
def build_truncate_statements(*table_names)
|
168
|
+
"TRUNCATE TABLE #{table_names.map(&method(:quote_table_name)).join(", ")}"
|
169
|
+
end
|
170
|
+
|
167
171
|
# Returns the current ID of a table's sequence.
|
168
172
|
def last_insert_id_result(sequence_name)
|
169
173
|
exec_query("SELECT currval(#{quote(sequence_name)})", "SQL")
|
@@ -26,9 +26,9 @@ module ActiveRecord
|
|
26
26
|
|
27
27
|
value = value.sub(/^\((.+)\)$/, '-\1') # (4)
|
28
28
|
case value
|
29
|
-
when /^-?\D
|
29
|
+
when /^-?\D*[\d,]+\.\d{2}$/ # (1)
|
30
30
|
value.gsub!(/[^-\d.]/, "")
|
31
|
-
when /^-?\D
|
31
|
+
when /^-?\D*[\d.]+,\d{2}$/ # (2)
|
32
32
|
value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
|
33
33
|
end
|
34
34
|
|
@@ -30,7 +30,7 @@ module ActiveRecord
|
|
30
30
|
# - "schema.name".table_name
|
31
31
|
# - "schema.name"."table.name"
|
32
32
|
def quote_table_name(name) # :nodoc:
|
33
|
-
|
33
|
+
self.class.quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
|
34
34
|
end
|
35
35
|
|
36
36
|
# Quotes schema names for use in SQL queries.
|
@@ -44,7 +44,7 @@ module ActiveRecord
|
|
44
44
|
|
45
45
|
# Quotes column names for use in SQL queries.
|
46
46
|
def quote_column_name(name) # :nodoc:
|
47
|
-
|
47
|
+
self.class.quoted_column_names[name] ||= PG::Connection.quote_ident(super).freeze
|
48
48
|
end
|
49
49
|
|
50
50
|
# Quote date/time values for use in SQL input.
|
@@ -78,6 +78,43 @@ module ActiveRecord
|
|
78
78
|
type_map.lookup(column.oid, column.fmod, column.sql_type)
|
79
79
|
end
|
80
80
|
|
81
|
+
def column_name_matcher
|
82
|
+
COLUMN_NAME
|
83
|
+
end
|
84
|
+
|
85
|
+
def column_name_with_order_matcher
|
86
|
+
COLUMN_NAME_WITH_ORDER
|
87
|
+
end
|
88
|
+
|
89
|
+
COLUMN_NAME = /
|
90
|
+
\A
|
91
|
+
(
|
92
|
+
(?:
|
93
|
+
# "table_name"."column_name"::type_name | function(one or no argument)::type_name
|
94
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
|
95
|
+
)
|
96
|
+
(?:\s+AS\s+(?:\w+|"\w+"))?
|
97
|
+
)
|
98
|
+
(?:\s*,\s*\g<1>)*
|
99
|
+
\z
|
100
|
+
/ix
|
101
|
+
|
102
|
+
COLUMN_NAME_WITH_ORDER = /
|
103
|
+
\A
|
104
|
+
(
|
105
|
+
(?:
|
106
|
+
# "table_name"."column_name"::type_name | function(one or no argument)::type_name
|
107
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
|
108
|
+
)
|
109
|
+
(?:\s+ASC|\s+DESC)?
|
110
|
+
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
111
|
+
)
|
112
|
+
(?:\s*,\s*\g<1>)*
|
113
|
+
\z
|
114
|
+
/ix
|
115
|
+
|
116
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
117
|
+
|
81
118
|
private
|
82
119
|
def lookup_cast_type(sql_type)
|
83
120
|
super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
|
@@ -138,7 +175,7 @@ module ActiveRecord
|
|
138
175
|
end
|
139
176
|
|
140
177
|
def encode_range(range)
|
141
|
-
"[#{type_cast_range_value(range.
|
178
|
+
"[#{type_cast_range_value(range.begin)},#{type_cast_range_value(range.end)}#{range.exclude_end? ? ')' : ']'}"
|
142
179
|
end
|
143
180
|
|
144
181
|
def determine_encoding_of_strings_in_array(value)
|
@@ -17,6 +17,42 @@ module ActiveRecord
|
|
17
17
|
"VALIDATE CONSTRAINT #{quote_column_name(name)}"
|
18
18
|
end
|
19
19
|
|
20
|
+
def visit_ChangeColumnDefinition(o)
|
21
|
+
column = o.column
|
22
|
+
column.sql_type = type_to_sql(column.type, column.options)
|
23
|
+
quoted_column_name = quote_column_name(o.name)
|
24
|
+
|
25
|
+
change_column_sql = +"ALTER COLUMN #{quoted_column_name} TYPE #{column.sql_type}"
|
26
|
+
|
27
|
+
options = column_options(column)
|
28
|
+
|
29
|
+
if options[:collation]
|
30
|
+
change_column_sql << " COLLATE \"#{options[:collation]}\""
|
31
|
+
end
|
32
|
+
|
33
|
+
if options[:using]
|
34
|
+
change_column_sql << " USING #{options[:using]}"
|
35
|
+
elsif options[:cast_as]
|
36
|
+
cast_as_type = type_to_sql(options[:cast_as], options)
|
37
|
+
change_column_sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
|
38
|
+
end
|
39
|
+
|
40
|
+
if options.key?(:default)
|
41
|
+
if options[:default].nil?
|
42
|
+
change_column_sql << ", ALTER COLUMN #{quoted_column_name} DROP DEFAULT"
|
43
|
+
else
|
44
|
+
quoted_default = quote_default_expression(options[:default], column)
|
45
|
+
change_column_sql << ", ALTER COLUMN #{quoted_column_name} SET DEFAULT #{quoted_default}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if options.key?(:null)
|
50
|
+
change_column_sql << ", ALTER COLUMN #{quoted_column_name} #{options[:null] ? 'DROP' : 'SET'} NOT NULL"
|
51
|
+
end
|
52
|
+
|
53
|
+
change_column_sql
|
54
|
+
end
|
55
|
+
|
20
56
|
def add_column_options!(sql, options)
|
21
57
|
if options[:collation]
|
22
58
|
sql << " COLLATE \"#{options[:collation]}\""
|
@@ -4,6 +4,8 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module PostgreSQL
|
6
6
|
module ColumnMethods
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
7
9
|
# Defines the primary key field.
|
8
10
|
# Use of the native PostgreSQL UUID type is supported, and can be used
|
9
11
|
# by defining your tables as such:
|
@@ -51,124 +53,131 @@ module ActiveRecord
|
|
51
53
|
super
|
52
54
|
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
|
56
|
+
##
|
57
|
+
# :method: bigserial
|
58
|
+
# :call-seq: bigserial(*names, **options)
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
60
|
+
##
|
61
|
+
# :method: bit
|
62
|
+
# :call-seq: bit(*names, **options)
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
##
|
65
|
+
# :method: bit_varying
|
66
|
+
# :call-seq: bit_varying(*names, **options)
|
65
67
|
|
66
|
-
|
67
|
-
|
68
|
-
|
68
|
+
##
|
69
|
+
# :method: cidr
|
70
|
+
# :call-seq: cidr(*names, **options)
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
-
|
72
|
+
##
|
73
|
+
# :method: citext
|
74
|
+
# :call-seq: citext(*names, **options)
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
##
|
77
|
+
# :method: daterange
|
78
|
+
# :call-seq: daterange(*names, **options)
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
80
|
+
##
|
81
|
+
# :method: hstore
|
82
|
+
# :call-seq: hstore(*names, **options)
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
##
|
85
|
+
# :method: inet
|
86
|
+
# :call-seq: inet(*names, **options)
|
85
87
|
|
86
|
-
|
87
|
-
|
88
|
-
|
88
|
+
##
|
89
|
+
# :method: interval
|
90
|
+
# :call-seq: interval(*names, **options)
|
89
91
|
|
90
|
-
|
91
|
-
|
92
|
-
|
92
|
+
##
|
93
|
+
# :method: int4range
|
94
|
+
# :call-seq: int4range(*names, **options)
|
93
95
|
|
94
|
-
|
95
|
-
|
96
|
-
|
96
|
+
##
|
97
|
+
# :method: int8range
|
98
|
+
# :call-seq: int8range(*names, **options)
|
97
99
|
|
98
|
-
|
99
|
-
|
100
|
-
|
100
|
+
##
|
101
|
+
# :method: jsonb
|
102
|
+
# :call-seq: jsonb(*names, **options)
|
101
103
|
|
102
|
-
|
103
|
-
|
104
|
-
|
104
|
+
##
|
105
|
+
# :method: ltree
|
106
|
+
# :call-seq: ltree(*names, **options)
|
105
107
|
|
106
|
-
|
107
|
-
|
108
|
-
|
108
|
+
##
|
109
|
+
# :method: macaddr
|
110
|
+
# :call-seq: macaddr(*names, **options)
|
109
111
|
|
110
|
-
|
111
|
-
|
112
|
-
|
112
|
+
##
|
113
|
+
# :method: money
|
114
|
+
# :call-seq: money(*names, **options)
|
113
115
|
|
114
|
-
|
115
|
-
|
116
|
-
|
116
|
+
##
|
117
|
+
# :method: numrange
|
118
|
+
# :call-seq: numrange(*names, **options)
|
117
119
|
|
118
|
-
|
119
|
-
|
120
|
-
|
120
|
+
##
|
121
|
+
# :method: oid
|
122
|
+
# :call-seq: oid(*names, **options)
|
121
123
|
|
122
|
-
|
123
|
-
|
124
|
-
|
124
|
+
##
|
125
|
+
# :method: point
|
126
|
+
# :call-seq: point(*names, **options)
|
125
127
|
|
126
|
-
|
127
|
-
|
128
|
-
|
128
|
+
##
|
129
|
+
# :method: line
|
130
|
+
# :call-seq: line(*names, **options)
|
129
131
|
|
130
|
-
|
131
|
-
|
132
|
-
|
132
|
+
##
|
133
|
+
# :method: lseg
|
134
|
+
# :call-seq: lseg(*names, **options)
|
133
135
|
|
134
|
-
|
135
|
-
|
136
|
-
|
136
|
+
##
|
137
|
+
# :method: box
|
138
|
+
# :call-seq: box(*names, **options)
|
137
139
|
|
138
|
-
|
139
|
-
|
140
|
-
|
140
|
+
##
|
141
|
+
# :method: path
|
142
|
+
# :call-seq: path(*names, **options)
|
141
143
|
|
142
|
-
|
143
|
-
|
144
|
-
|
144
|
+
##
|
145
|
+
# :method: polygon
|
146
|
+
# :call-seq: polygon(*names, **options)
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
-
|
148
|
+
##
|
149
|
+
# :method: circle
|
150
|
+
# :call-seq: circle(*names, **options)
|
149
151
|
|
150
|
-
|
151
|
-
|
152
|
-
|
152
|
+
##
|
153
|
+
# :method: serial
|
154
|
+
# :call-seq: serial(*names, **options)
|
153
155
|
|
154
|
-
|
155
|
-
|
156
|
-
|
156
|
+
##
|
157
|
+
# :method: tsrange
|
158
|
+
# :call-seq: tsrange(*names, **options)
|
157
159
|
|
158
|
-
|
159
|
-
|
160
|
-
|
160
|
+
##
|
161
|
+
# :method: tstzrange
|
162
|
+
# :call-seq: tstzrange(*names, **options)
|
161
163
|
|
162
|
-
|
163
|
-
|
164
|
-
|
164
|
+
##
|
165
|
+
# :method: tsvector
|
166
|
+
# :call-seq: tsvector(*names, **options)
|
165
167
|
|
166
|
-
|
167
|
-
|
168
|
-
|
168
|
+
##
|
169
|
+
# :method: uuid
|
170
|
+
# :call-seq: uuid(*names, **options)
|
171
|
+
|
172
|
+
##
|
173
|
+
# :method: xml
|
174
|
+
# :call-seq: xml(*names, **options)
|
169
175
|
|
170
|
-
|
171
|
-
|
176
|
+
included do
|
177
|
+
define_column_methods :bigserial, :bit, :bit_varying, :cidr, :citext, :daterange,
|
178
|
+
:hstore, :inet, :interval, :int4range, :int8range, :jsonb, :ltree, :macaddr,
|
179
|
+
:money, :numrange, :oid, :point, :line, :lseg, :box, :path, :polygon, :circle,
|
180
|
+
:serial, :tsrange, :tstzrange, :tsvector, :uuid, :xml
|
172
181
|
end
|
173
182
|
end
|
174
183
|
|
@@ -287,7 +287,7 @@ module ActiveRecord
|
|
287
287
|
quoted_sequence = quote_table_name(sequence)
|
288
288
|
max_pk = query_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}", "SCHEMA")
|
289
289
|
if max_pk.nil?
|
290
|
-
if
|
290
|
+
if database_version >= 100000
|
291
291
|
minvalue = query_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass", "SCHEMA")
|
292
292
|
else
|
293
293
|
minvalue = query_value("SELECT min_value FROM #{quoted_sequence}", "SCHEMA")
|
@@ -368,31 +368,6 @@ module ActiveRecord
|
|
368
368
|
SQL
|
369
369
|
end
|
370
370
|
|
371
|
-
def bulk_change_table(table_name, operations)
|
372
|
-
sql_fragments = []
|
373
|
-
non_combinable_operations = []
|
374
|
-
|
375
|
-
operations.each do |command, args|
|
376
|
-
table, arguments = args.shift, args
|
377
|
-
method = :"#{command}_for_alter"
|
378
|
-
|
379
|
-
if respond_to?(method, true)
|
380
|
-
sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
|
381
|
-
sql_fragments << sqls
|
382
|
-
non_combinable_operations.concat(procs)
|
383
|
-
else
|
384
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
|
385
|
-
non_combinable_operations.each(&:call)
|
386
|
-
sql_fragments = []
|
387
|
-
non_combinable_operations = []
|
388
|
-
send(command, table, *arguments)
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
|
393
|
-
non_combinable_operations.each(&:call)
|
394
|
-
end
|
395
|
-
|
396
371
|
# Renames a table.
|
397
372
|
# Also renames a table's primary key sequence if the sequence name exists and
|
398
373
|
# matches the Active Record default.
|
@@ -443,14 +418,16 @@ module ActiveRecord
|
|
443
418
|
end
|
444
419
|
|
445
420
|
# Adds comment for given table column or drops it if +comment+ is a +nil+
|
446
|
-
def change_column_comment(table_name, column_name,
|
421
|
+
def change_column_comment(table_name, column_name, comment_or_changes) # :nodoc:
|
447
422
|
clear_cache!
|
423
|
+
comment = extract_new_comment_value(comment_or_changes)
|
448
424
|
execute "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} IS #{quote(comment)}"
|
449
425
|
end
|
450
426
|
|
451
427
|
# Adds comment for given table or drops it if +comment+ is a +nil+
|
452
|
-
def change_table_comment(table_name,
|
428
|
+
def change_table_comment(table_name, comment_or_changes) # :nodoc:
|
453
429
|
clear_cache!
|
430
|
+
comment = extract_new_comment_value(comment_or_changes)
|
454
431
|
execute "COMMENT ON TABLE #{quote_table_name(table_name)} IS #{quote(comment)}"
|
455
432
|
end
|
456
433
|
|
@@ -548,21 +525,21 @@ module ActiveRecord
|
|
548
525
|
# The hard limit is 1GB, because of a 32-bit size field, and TOAST.
|
549
526
|
case limit
|
550
527
|
when nil, 0..0x3fffffff; super(type)
|
551
|
-
else raise
|
528
|
+
else raise ArgumentError, "No binary type has byte size #{limit}. The limit on binary can be at most 1GB - 1byte."
|
552
529
|
end
|
553
530
|
when "text"
|
554
531
|
# PostgreSQL doesn't support limits on text columns.
|
555
532
|
# The hard limit is 1GB, according to section 8.3 in the manual.
|
556
533
|
case limit
|
557
534
|
when nil, 0..0x3fffffff; super(type)
|
558
|
-
else raise
|
535
|
+
else raise ArgumentError, "No text type has byte size #{limit}. The limit on text can be at most 1GB - 1byte."
|
559
536
|
end
|
560
537
|
when "integer"
|
561
538
|
case limit
|
562
539
|
when 1, 2; "smallint"
|
563
540
|
when nil, 3, 4; "integer"
|
564
541
|
when 5..8; "bigint"
|
565
|
-
else raise
|
542
|
+
else raise ArgumentError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead."
|
566
543
|
end
|
567
544
|
else
|
568
545
|
super
|
@@ -623,10 +600,10 @@ module ActiveRecord
|
|
623
600
|
# validate_foreign_key :accounts, name: :special_fk_name
|
624
601
|
#
|
625
602
|
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key.
|
626
|
-
def validate_foreign_key(from_table,
|
603
|
+
def validate_foreign_key(from_table, to_table = nil, **options)
|
627
604
|
return unless supports_validate_constraints?
|
628
605
|
|
629
|
-
fk_name_to_validate = foreign_key_for!(from_table,
|
606
|
+
fk_name_to_validate = foreign_key_for!(from_table, to_table: to_table, **options).name
|
630
607
|
|
631
608
|
validate_constraint from_table, fk_name_to_validate
|
632
609
|
end
|
@@ -637,7 +614,7 @@ module ActiveRecord
|
|
637
614
|
end
|
638
615
|
|
639
616
|
def create_table_definition(*args)
|
640
|
-
PostgreSQL::TableDefinition.new(*args)
|
617
|
+
PostgreSQL::TableDefinition.new(self, *args)
|
641
618
|
end
|
642
619
|
|
643
620
|
def create_alter_table(name)
|
@@ -650,16 +627,19 @@ module ActiveRecord
|
|
650
627
|
default_value = extract_value_from_default(default)
|
651
628
|
default_function = extract_default_function(default_value, default)
|
652
629
|
|
653
|
-
|
630
|
+
if match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/)
|
631
|
+
serial = sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
|
632
|
+
end
|
633
|
+
|
634
|
+
PostgreSQL::Column.new(
|
654
635
|
column_name,
|
655
636
|
default_value,
|
656
637
|
type_metadata,
|
657
638
|
!notnull,
|
658
|
-
table_name,
|
659
639
|
default_function,
|
660
|
-
collation,
|
640
|
+
collation: collation,
|
661
641
|
comment: comment.presence,
|
662
|
-
|
642
|
+
serial: serial
|
663
643
|
)
|
664
644
|
end
|
665
645
|
|
@@ -672,7 +652,23 @@ module ActiveRecord
|
|
672
652
|
precision: cast_type.precision,
|
673
653
|
scale: cast_type.scale,
|
674
654
|
)
|
675
|
-
|
655
|
+
PostgreSQL::TypeMetadata.new(simple_type, oid: oid, fmod: fmod)
|
656
|
+
end
|
657
|
+
|
658
|
+
def sequence_name_from_parts(table_name, column_name, suffix)
|
659
|
+
over_length = [table_name, column_name, suffix].sum(&:length) + 2 - max_identifier_length
|
660
|
+
|
661
|
+
if over_length > 0
|
662
|
+
column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
|
663
|
+
over_length -= column_name.length - column_name_length
|
664
|
+
column_name = column_name[0, column_name_length - [over_length, 0].min]
|
665
|
+
end
|
666
|
+
|
667
|
+
if over_length > 0
|
668
|
+
table_name = table_name[0, table_name.length - over_length]
|
669
|
+
end
|
670
|
+
|
671
|
+
"#{table_name}_#{column_name}_#{suffix}"
|
676
672
|
end
|
677
673
|
|
678
674
|
def extract_foreign_key_action(specifier)
|
@@ -683,38 +679,20 @@ module ActiveRecord
|
|
683
679
|
end
|
684
680
|
end
|
685
681
|
|
686
|
-
def change_column_sql(table_name, column_name, type, options = {})
|
687
|
-
quoted_column_name = quote_column_name(column_name)
|
688
|
-
sql_type = type_to_sql(type, options)
|
689
|
-
sql = +"ALTER COLUMN #{quoted_column_name} TYPE #{sql_type}"
|
690
|
-
if options[:collation]
|
691
|
-
sql << " COLLATE \"#{options[:collation]}\""
|
692
|
-
end
|
693
|
-
if options[:using]
|
694
|
-
sql << " USING #{options[:using]}"
|
695
|
-
elsif options[:cast_as]
|
696
|
-
cast_as_type = type_to_sql(options[:cast_as], options)
|
697
|
-
sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
|
698
|
-
end
|
699
|
-
|
700
|
-
sql
|
701
|
-
end
|
702
|
-
|
703
682
|
def add_column_for_alter(table_name, column_name, type, options = {})
|
704
683
|
return super unless options.key?(:comment)
|
705
684
|
[super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
|
706
685
|
end
|
707
686
|
|
708
687
|
def change_column_for_alter(table_name, column_name, type, options = {})
|
709
|
-
|
710
|
-
|
711
|
-
sqls
|
688
|
+
td = create_table_definition(table_name)
|
689
|
+
cd = td.new_column_definition(column_name, type, options)
|
690
|
+
sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))]
|
712
691
|
sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment)
|
713
692
|
sqls
|
714
693
|
end
|
715
694
|
|
716
|
-
|
717
|
-
def change_column_default_for_alter(table_name, column_name, default_or_changes) # :nodoc:
|
695
|
+
def change_column_default_for_alter(table_name, column_name, default_or_changes)
|
718
696
|
column = column_for(table_name, column_name)
|
719
697
|
return unless column
|
720
698
|
|
@@ -729,11 +707,17 @@ module ActiveRecord
|
|
729
707
|
end
|
730
708
|
end
|
731
709
|
|
732
|
-
def change_column_null_for_alter(table_name, column_name, null, default = nil)
|
733
|
-
"ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
|
710
|
+
def change_column_null_for_alter(table_name, column_name, null, default = nil)
|
711
|
+
"ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
|
734
712
|
end
|
735
713
|
|
736
714
|
def add_timestamps_for_alter(table_name, options = {})
|
715
|
+
options[:null] = false if options[:null].nil?
|
716
|
+
|
717
|
+
if !options.key?(:precision) && supports_datetime_with_precision?
|
718
|
+
options[:precision] = 6
|
719
|
+
end
|
720
|
+
|
737
721
|
[add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
|
738
722
|
end
|
739
723
|
|