activerecord 5.0.7.2 → 5.1.0.beta1
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 +5 -5
- data/CHANGELOG.md +389 -2252
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +110 -93
- data/lib/active_record/counter_cache.rb +62 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +58 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +125 -140
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -11,11 +11,22 @@ module ActiveRecord
|
|
11
11
|
# t.timestamps
|
12
12
|
# end
|
13
13
|
#
|
14
|
-
# By default, this will use the +
|
15
|
-
# +
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
14
|
+
# By default, this will use the +gen_random_uuid()+ function from the
|
15
|
+
# +pgcrypto+ extension. As that extension is only available in
|
16
|
+
# PostgreSQL 9.4+, for earlier versions an explicit default can be set
|
17
|
+
# to use +uuid_generate_v4()+ from the +uuid-ossp+ extension instead:
|
18
|
+
#
|
19
|
+
# create_table :stuffs, id: false do |t|
|
20
|
+
# t.primary_key :id, :uuid, default: "uuid_generate_v4()"
|
21
|
+
# t.uuid :foo_id
|
22
|
+
# t.timestamps
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# To enable the appropriate extension, which is a requirement, use
|
26
|
+
# the +enable_extension+ method in your migrations.
|
27
|
+
#
|
28
|
+
# To use a UUID primary key without any of the extensions, set the
|
29
|
+
# +:default+ option to +nil+:
|
19
30
|
#
|
20
31
|
# create_table :stuffs, id: false do |t|
|
21
32
|
# t.primary_key :id, :uuid, default: nil
|
@@ -23,15 +34,25 @@ module ActiveRecord
|
|
23
34
|
# t.timestamps
|
24
35
|
# end
|
25
36
|
#
|
26
|
-
# You may also pass a
|
27
|
-
#
|
37
|
+
# You may also pass a custom stored procedure that returns a UUID or use a
|
38
|
+
# different UUID generation function from another library.
|
28
39
|
#
|
29
40
|
# Note that setting the UUID primary key default value to +nil+ will
|
30
41
|
# require you to assure that you always provide a UUID value before saving
|
31
42
|
# a record (as primary keys cannot be +nil+). This might be done via the
|
32
43
|
# +SecureRandom.uuid+ method and a +before_save+ callback, for instance.
|
33
44
|
def primary_key(name, type = :primary_key, **options)
|
34
|
-
options[:
|
45
|
+
options[:auto_increment] = true if [:integer, :bigint].include?(type) && !options.key?(:default)
|
46
|
+
if type == :uuid
|
47
|
+
options[:default] = options.fetch(:default, "gen_random_uuid()")
|
48
|
+
elsif options.delete(:auto_increment) == true && %i(integer bigint).include?(type)
|
49
|
+
type = if type == :bigint || options[:limit] == 8
|
50
|
+
:bigserial
|
51
|
+
else
|
52
|
+
:serial
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
35
56
|
super
|
36
57
|
end
|
37
58
|
|
@@ -67,6 +88,10 @@ module ActiveRecord
|
|
67
88
|
args.each { |name| column(name, :inet, options) }
|
68
89
|
end
|
69
90
|
|
91
|
+
def interval(*args, **options)
|
92
|
+
args.each { |name| column(name, :interval, options) }
|
93
|
+
end
|
94
|
+
|
70
95
|
def int4range(*args, **options)
|
71
96
|
args.each { |name| column(name, :int4range, options) }
|
72
97
|
end
|
@@ -99,6 +124,10 @@ module ActiveRecord
|
|
99
124
|
args.each { |name| column(name, :numrange, options) }
|
100
125
|
end
|
101
126
|
|
127
|
+
def oid(*args, **options)
|
128
|
+
args.each { |name| column(name, :oid, options) }
|
129
|
+
end
|
130
|
+
|
102
131
|
def point(*args, **options)
|
103
132
|
args.each { |name| column(name, :point, options) }
|
104
133
|
end
|
@@ -152,24 +181,8 @@ module ActiveRecord
|
|
152
181
|
end
|
153
182
|
end
|
154
183
|
|
155
|
-
class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
|
156
|
-
attr_accessor :array
|
157
|
-
end
|
158
|
-
|
159
184
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
160
185
|
include ColumnMethods
|
161
|
-
|
162
|
-
def new_column_definition(name, type, options) # :nodoc:
|
163
|
-
column = super
|
164
|
-
column.array = options[:array]
|
165
|
-
column
|
166
|
-
end
|
167
|
-
|
168
|
-
private
|
169
|
-
|
170
|
-
def create_column_definition(name, type)
|
171
|
-
PostgreSQL::ColumnDefinition.new name, type
|
172
|
-
end
|
173
186
|
end
|
174
187
|
|
175
188
|
class Table < ActiveRecord::ConnectionAdapters::Table
|
@@ -1,19 +1,11 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
module PostgreSQL
|
4
|
-
module ColumnDumper
|
5
|
-
def column_spec_for_primary_key(column)
|
6
|
-
spec = super
|
7
|
-
if schema_type(column) == :uuid
|
8
|
-
spec[:default] ||= 'nil'
|
9
|
-
end
|
10
|
-
spec
|
11
|
-
end
|
12
|
-
|
4
|
+
module ColumnDumper # :nodoc:
|
13
5
|
# Adds +:array+ option to the default set
|
14
6
|
def prepare_column_options(column)
|
15
7
|
spec = super
|
16
|
-
spec[:array] =
|
8
|
+
spec[:array] = "true" if column.array?
|
17
9
|
spec
|
18
10
|
end
|
19
11
|
|
@@ -24,23 +16,27 @@ module ActiveRecord
|
|
24
16
|
|
25
17
|
private
|
26
18
|
|
27
|
-
|
28
|
-
|
29
|
-
|
19
|
+
def default_primary_key?(column)
|
20
|
+
schema_type(column) == :bigserial
|
21
|
+
end
|
22
|
+
|
23
|
+
def explicit_primary_key_default?(column)
|
24
|
+
column.type == :uuid || (column.type == :integer && !column.serial?)
|
25
|
+
end
|
30
26
|
|
31
|
-
|
32
|
-
|
27
|
+
def schema_type(column)
|
28
|
+
return super unless column.serial?
|
33
29
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
if column.bigint?
|
31
|
+
:bigserial
|
32
|
+
else
|
33
|
+
:serial
|
34
|
+
end
|
38
35
|
end
|
39
|
-
end
|
40
36
|
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
def schema_expression(column)
|
38
|
+
super unless column.serial?
|
39
|
+
end
|
44
40
|
end
|
45
41
|
end
|
46
42
|
end
|
@@ -1,24 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/core_ext/string/strip"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
module PostgreSQL
|
6
|
-
class SchemaCreation < AbstractAdapter::SchemaCreation
|
7
|
-
private
|
8
|
-
|
9
|
-
def visit_ColumnDefinition(o)
|
10
|
-
o.sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale, o.array)
|
11
|
-
super
|
12
|
-
end
|
13
|
-
|
14
|
-
def add_column_options!(sql, options)
|
15
|
-
if options[:collation]
|
16
|
-
sql << " COLLATE \"#{options[:collation]}\""
|
17
|
-
end
|
18
|
-
super
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
6
|
module SchemaStatements
|
23
7
|
# Drops the database specified on the +name+ attribute
|
24
8
|
# and creates it again using the provided +options+.
|
@@ -36,26 +20,26 @@ module ActiveRecord
|
|
36
20
|
# create_database config[:database], config
|
37
21
|
# create_database 'foo_development', encoding: 'unicode'
|
38
22
|
def create_database(name, options = {})
|
39
|
-
options = { encoding:
|
23
|
+
options = { encoding: "utf8" }.merge!(options.symbolize_keys)
|
40
24
|
|
41
25
|
option_string = options.inject("") do |memo, (key, value)|
|
42
26
|
memo += case key
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
27
|
+
when :owner
|
28
|
+
" OWNER = \"#{value}\""
|
29
|
+
when :template
|
30
|
+
" TEMPLATE = \"#{value}\""
|
31
|
+
when :encoding
|
32
|
+
" ENCODING = '#{value}'"
|
33
|
+
when :collation
|
34
|
+
" LC_COLLATE = '#{value}'"
|
35
|
+
when :ctype
|
36
|
+
" LC_CTYPE = '#{value}'"
|
37
|
+
when :tablespace
|
38
|
+
" TABLESPACE = \"#{value}\""
|
39
|
+
when :connection_limit
|
40
|
+
" CONNECTION LIMIT = #{value}"
|
57
41
|
else
|
58
|
-
|
42
|
+
""
|
59
43
|
end
|
60
44
|
end
|
61
45
|
|
@@ -71,22 +55,26 @@ module ActiveRecord
|
|
71
55
|
end
|
72
56
|
|
73
57
|
# Returns the list of all tables in the schema search path.
|
74
|
-
def tables
|
75
|
-
|
76
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
77
|
-
Passing arguments to #tables is deprecated without replacement.
|
78
|
-
MSG
|
79
|
-
end
|
80
|
-
|
81
|
-
select_values("SELECT tablename FROM pg_tables WHERE schemaname = ANY(current_schemas(false))", 'SCHEMA')
|
58
|
+
def tables
|
59
|
+
select_values("SELECT tablename FROM pg_tables WHERE schemaname = ANY(current_schemas(false))", "SCHEMA")
|
82
60
|
end
|
83
61
|
|
84
62
|
def data_sources # :nodoc
|
85
|
-
select_values(<<-SQL,
|
63
|
+
select_values(<<-SQL, "SCHEMA")
|
86
64
|
SELECT c.relname
|
87
65
|
FROM pg_class c
|
88
66
|
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
89
|
-
WHERE c.relkind IN ('r',
|
67
|
+
WHERE c.relkind IN ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view
|
68
|
+
AND n.nspname = ANY (current_schemas(false))
|
69
|
+
SQL
|
70
|
+
end
|
71
|
+
|
72
|
+
def views # :nodoc:
|
73
|
+
select_values(<<-SQL, "SCHEMA")
|
74
|
+
SELECT c.relname
|
75
|
+
FROM pg_class c
|
76
|
+
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
77
|
+
WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
|
90
78
|
AND n.nspname = ANY (current_schemas(false))
|
91
79
|
SQL
|
92
80
|
end
|
@@ -95,36 +83,28 @@ module ActiveRecord
|
|
95
83
|
# If the schema is not specified as part of +name+ then it will only find tables within
|
96
84
|
# the current schema search path (regardless of permissions to access tables in other schemas)
|
97
85
|
def table_exists?(name)
|
98
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
99
|
-
#table_exists? currently checks both tables and views.
|
100
|
-
This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
|
101
|
-
Use #data_source_exists? instead.
|
102
|
-
MSG
|
103
|
-
|
104
|
-
data_source_exists?(name)
|
105
|
-
end
|
106
|
-
|
107
|
-
def data_source_exists?(name)
|
108
86
|
name = Utils.extract_schema_qualified_name(name.to_s)
|
109
87
|
return false unless name.identifier
|
110
88
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
AND c.relname = '#{name.identifier}'
|
117
|
-
AND n.nspname = #{name.schema ? "'#{name.schema}'" : 'ANY (current_schemas(false))'}
|
89
|
+
select_values(<<-SQL, "SCHEMA").any?
|
90
|
+
SELECT tablename
|
91
|
+
FROM pg_tables
|
92
|
+
WHERE tablename = #{quote(name.identifier)}
|
93
|
+
AND schemaname = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
|
118
94
|
SQL
|
119
95
|
end
|
120
96
|
|
121
|
-
def
|
122
|
-
|
97
|
+
def data_source_exists?(name) # :nodoc:
|
98
|
+
name = Utils.extract_schema_qualified_name(name.to_s)
|
99
|
+
return false unless name.identifier
|
100
|
+
|
101
|
+
select_values(<<-SQL, "SCHEMA").any?
|
123
102
|
SELECT c.relname
|
124
103
|
FROM pg_class c
|
125
104
|
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
126
|
-
WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
|
127
|
-
AND
|
105
|
+
WHERE c.relkind IN ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view
|
106
|
+
AND c.relname = #{quote(name.identifier)}
|
107
|
+
AND n.nspname = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
|
128
108
|
SQL
|
129
109
|
end
|
130
110
|
|
@@ -132,13 +112,13 @@ module ActiveRecord
|
|
132
112
|
name = Utils.extract_schema_qualified_name(view_name.to_s)
|
133
113
|
return false unless name.identifier
|
134
114
|
|
135
|
-
select_values(<<-SQL,
|
115
|
+
select_values(<<-SQL, "SCHEMA").any?
|
136
116
|
SELECT c.relname
|
137
117
|
FROM pg_class c
|
138
118
|
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
139
119
|
WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
|
140
|
-
AND c.relname =
|
141
|
-
AND n.nspname = #{name.schema ?
|
120
|
+
AND c.relname = #{quote(name.identifier)}
|
121
|
+
AND n.nspname = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
|
142
122
|
SQL
|
143
123
|
end
|
144
124
|
|
@@ -148,15 +128,20 @@ module ActiveRecord
|
|
148
128
|
|
149
129
|
# Returns true if schema exists.
|
150
130
|
def schema_exists?(name)
|
151
|
-
select_value("SELECT COUNT(*) FROM pg_namespace WHERE nspname = '#{name}'",
|
131
|
+
select_value("SELECT COUNT(*) FROM pg_namespace WHERE nspname = '#{name}'", "SCHEMA").to_i > 0
|
152
132
|
end
|
153
133
|
|
154
134
|
# Verifies existence of an index with a given name.
|
155
|
-
def index_name_exists?(table_name, index_name, default)
|
135
|
+
def index_name_exists?(table_name, index_name, default = nil)
|
136
|
+
unless default.nil?
|
137
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
138
|
+
Passing default to #index_name_exists? is deprecated without replacement.
|
139
|
+
MSG
|
140
|
+
end
|
156
141
|
table = Utils.extract_schema_qualified_name(table_name.to_s)
|
157
142
|
index = Utils.extract_schema_qualified_name(index_name.to_s)
|
158
143
|
|
159
|
-
select_value(<<-SQL,
|
144
|
+
select_value(<<-SQL, "SCHEMA").to_i > 0
|
160
145
|
SELECT COUNT(*)
|
161
146
|
FROM pg_class t
|
162
147
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
@@ -170,10 +155,16 @@ module ActiveRecord
|
|
170
155
|
end
|
171
156
|
|
172
157
|
# Returns an array of indexes for the given table.
|
173
|
-
def indexes(table_name, name = nil)
|
158
|
+
def indexes(table_name, name = nil) # :nodoc:
|
159
|
+
if name
|
160
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
161
|
+
Passing name to #indexes is deprecated without replacement.
|
162
|
+
MSG
|
163
|
+
end
|
164
|
+
|
174
165
|
table = Utils.extract_schema_qualified_name(table_name.to_s)
|
175
166
|
|
176
|
-
result = query(<<-SQL,
|
167
|
+
result = query(<<-SQL, "SCHEMA")
|
177
168
|
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid,
|
178
169
|
pg_catalog.obj_description(i.oid, 'pg_class') AS comment,
|
179
170
|
(SELECT COUNT(*) FROM pg_opclass o
|
@@ -221,21 +212,23 @@ module ActiveRecord
|
|
221
212
|
end.compact
|
222
213
|
end
|
223
214
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
215
|
+
def new_column_from_field(table_name, field) # :nondoc:
|
216
|
+
column_name, type, default, notnull, oid, fmod, collation, comment = field
|
217
|
+
oid = oid.to_i
|
218
|
+
fmod = fmod.to_i
|
219
|
+
type_metadata = fetch_type_metadata(column_name, type, oid, fmod)
|
220
|
+
default_value = extract_value_from_default(default)
|
221
|
+
default_function = extract_default_function(default_value, default)
|
222
|
+
PostgreSQLColumn.new(
|
223
|
+
column_name,
|
224
|
+
default_value,
|
225
|
+
type_metadata,
|
226
|
+
!notnull,
|
227
|
+
table_name,
|
228
|
+
default_function,
|
229
|
+
collation,
|
230
|
+
comment: comment.presence
|
231
|
+
)
|
239
232
|
end
|
240
233
|
|
241
234
|
def table_options(table_name) # :nodoc:
|
@@ -248,7 +241,7 @@ module ActiveRecord
|
|
248
241
|
def table_comment(table_name) # :nodoc:
|
249
242
|
name = Utils.extract_schema_qualified_name(table_name.to_s)
|
250
243
|
if name.identifier
|
251
|
-
select_value(<<-SQL.strip_heredoc,
|
244
|
+
select_value(<<-SQL.strip_heredoc, "SCHEMA")
|
252
245
|
SELECT pg_catalog.obj_description(c.oid, 'pg_class')
|
253
246
|
FROM pg_catalog.pg_class c
|
254
247
|
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
|
@@ -261,32 +254,32 @@ module ActiveRecord
|
|
261
254
|
|
262
255
|
# Returns the current database name.
|
263
256
|
def current_database
|
264
|
-
select_value(
|
257
|
+
select_value("select current_database()", "SCHEMA")
|
265
258
|
end
|
266
259
|
|
267
260
|
# Returns the current schema name.
|
268
261
|
def current_schema
|
269
|
-
select_value(
|
262
|
+
select_value("SELECT current_schema", "SCHEMA")
|
270
263
|
end
|
271
264
|
|
272
265
|
# Returns the current database encoding format.
|
273
266
|
def encoding
|
274
|
-
select_value("SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname LIKE '#{current_database}'",
|
267
|
+
select_value("SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname LIKE '#{current_database}'", "SCHEMA")
|
275
268
|
end
|
276
269
|
|
277
270
|
# Returns the current database collation.
|
278
271
|
def collation
|
279
|
-
select_value("SELECT datcollate FROM pg_database WHERE datname LIKE '#{current_database}'",
|
272
|
+
select_value("SELECT datcollate FROM pg_database WHERE datname LIKE '#{current_database}'", "SCHEMA")
|
280
273
|
end
|
281
274
|
|
282
275
|
# Returns the current database ctype.
|
283
276
|
def ctype
|
284
|
-
select_value("SELECT datctype FROM pg_database WHERE datname LIKE '#{current_database}'",
|
277
|
+
select_value("SELECT datctype FROM pg_database WHERE datname LIKE '#{current_database}'", "SCHEMA")
|
285
278
|
end
|
286
279
|
|
287
280
|
# Returns an array of schema names.
|
288
281
|
def schema_names
|
289
|
-
select_values(<<-SQL,
|
282
|
+
select_values(<<-SQL, "SCHEMA")
|
290
283
|
SELECT nspname
|
291
284
|
FROM pg_namespace
|
292
285
|
WHERE nspname !~ '^pg_.*'
|
@@ -296,7 +289,7 @@ module ActiveRecord
|
|
296
289
|
end
|
297
290
|
|
298
291
|
# Creates a schema for the given schema name.
|
299
|
-
def create_schema
|
292
|
+
def create_schema(schema_name)
|
300
293
|
execute "CREATE SCHEMA #{quote_schema_name(schema_name)}"
|
301
294
|
end
|
302
295
|
|
@@ -312,37 +305,37 @@ module ActiveRecord
|
|
312
305
|
# This should be not be called manually but set in database.yml.
|
313
306
|
def schema_search_path=(schema_csv)
|
314
307
|
if schema_csv
|
315
|
-
execute("SET search_path TO #{schema_csv}",
|
308
|
+
execute("SET search_path TO #{schema_csv}", "SCHEMA")
|
316
309
|
@schema_search_path = schema_csv
|
317
310
|
end
|
318
311
|
end
|
319
312
|
|
320
313
|
# Returns the active schema search path.
|
321
314
|
def schema_search_path
|
322
|
-
@schema_search_path ||= select_value(
|
315
|
+
@schema_search_path ||= select_value("SHOW search_path", "SCHEMA")
|
323
316
|
end
|
324
317
|
|
325
318
|
# Returns the current client message level.
|
326
319
|
def client_min_messages
|
327
|
-
select_value(
|
320
|
+
select_value("SHOW client_min_messages", "SCHEMA")
|
328
321
|
end
|
329
322
|
|
330
323
|
# Set the client message level.
|
331
324
|
def client_min_messages=(level)
|
332
|
-
execute("SET client_min_messages TO '#{level}'",
|
325
|
+
execute("SET client_min_messages TO '#{level}'", "SCHEMA")
|
333
326
|
end
|
334
327
|
|
335
328
|
# Returns the sequence name for a table's primary key or some other specified key.
|
336
|
-
def default_sequence_name(table_name, pk =
|
337
|
-
result = serial_sequence(table_name, pk
|
329
|
+
def default_sequence_name(table_name, pk = "id") #:nodoc:
|
330
|
+
result = serial_sequence(table_name, pk)
|
338
331
|
return nil unless result
|
339
332
|
Utils.extract_schema_qualified_name(result).to_s
|
340
333
|
rescue ActiveRecord::StatementInvalid
|
341
|
-
PostgreSQL::Name.new(nil, "#{table_name}_#{pk
|
334
|
+
PostgreSQL::Name.new(nil, "#{table_name}_#{pk}_seq").to_s
|
342
335
|
end
|
343
336
|
|
344
337
|
def serial_sequence(table, column)
|
345
|
-
select_value("SELECT pg_get_serial_sequence('#{table}', '#{column}')",
|
338
|
+
select_value("SELECT pg_get_serial_sequence('#{table}', '#{column}')", "SCHEMA")
|
346
339
|
end
|
347
340
|
|
348
341
|
# Sets the sequence of a table's primary key to the specified value.
|
@@ -353,7 +346,7 @@ module ActiveRecord
|
|
353
346
|
if sequence
|
354
347
|
quoted_sequence = quote_table_name(sequence)
|
355
348
|
|
356
|
-
select_value("SELECT setval('#{quoted_sequence}', #{value})",
|
349
|
+
select_value("SELECT setval('#{quoted_sequence}', #{value})", "SCHEMA")
|
357
350
|
else
|
358
351
|
@logger.warn "#{table} has primary key #{pk} with no default sequence." if @logger
|
359
352
|
end
|
@@ -362,7 +355,7 @@ module ActiveRecord
|
|
362
355
|
|
363
356
|
# Resets the sequence of a table's primary key to the maximum value.
|
364
357
|
def reset_pk_sequence!(table, pk = nil, sequence = nil) #:nodoc:
|
365
|
-
unless pk
|
358
|
+
unless pk && sequence
|
366
359
|
default_pk, default_sequence = pk_and_sequence_for(table)
|
367
360
|
|
368
361
|
pk ||= default_pk
|
@@ -375,17 +368,9 @@ module ActiveRecord
|
|
375
368
|
|
376
369
|
if pk && sequence
|
377
370
|
quoted_sequence = quote_table_name(sequence)
|
378
|
-
max_pk = select_value("select MAX(#{quote_column_name pk}) from #{quote_table_name(table)}")
|
379
|
-
if max_pk.nil?
|
380
|
-
if postgresql_version >= 100000
|
381
|
-
minvalue = select_value("SELECT seqmin from pg_sequence where seqrelid = '#{quoted_sequence}'::regclass")
|
382
|
-
else
|
383
|
-
minvalue = select_value("SELECT min_value FROM #{quoted_sequence}")
|
384
|
-
end
|
385
|
-
end
|
386
371
|
|
387
372
|
select_value(<<-end_sql, "SCHEMA")
|
388
|
-
SELECT setval('#{quoted_sequence}', #{
|
373
|
+
SELECT setval('#{quoted_sequence}', (SELECT COALESCE(MAX(#{quote_column_name pk})+(SELECT increment_by FROM #{quoted_sequence}), (SELECT min_value FROM #{quoted_sequence})) FROM #{quote_table_name(table)}), false)
|
389
374
|
end_sql
|
390
375
|
end
|
391
376
|
end
|
@@ -394,7 +379,7 @@ module ActiveRecord
|
|
394
379
|
def pk_and_sequence_for(table) #:nodoc:
|
395
380
|
# First try looking for a sequence with a dependency on the
|
396
381
|
# given table's primary key.
|
397
|
-
result = query(<<-end_sql,
|
382
|
+
result = query(<<-end_sql, "SCHEMA")[0]
|
398
383
|
SELECT attr.attname, nsp.nspname, seq.relname
|
399
384
|
FROM pg_class seq,
|
400
385
|
pg_attribute attr,
|
@@ -413,8 +398,8 @@ module ActiveRecord
|
|
413
398
|
AND dep.refobjid = '#{quote_table_name(table)}'::regclass
|
414
399
|
end_sql
|
415
400
|
|
416
|
-
if result.nil?
|
417
|
-
result = query(<<-end_sql,
|
401
|
+
if result.nil? || result.empty?
|
402
|
+
result = query(<<-end_sql, "SCHEMA")[0]
|
418
403
|
SELECT attr.attname, nsp.nspname,
|
419
404
|
CASE
|
420
405
|
WHEN pg_get_expr(def.adbin, def.adrelid) !~* 'nextval' THEN NULL
|
@@ -445,17 +430,18 @@ module ActiveRecord
|
|
445
430
|
end
|
446
431
|
|
447
432
|
def primary_keys(table_name) # :nodoc:
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
433
|
+
name = Utils.extract_schema_qualified_name(table_name.to_s)
|
434
|
+
select_values(<<-SQL.strip_heredoc, "SCHEMA")
|
435
|
+
SELECT column_name
|
436
|
+
FROM information_schema.key_column_usage kcu
|
437
|
+
JOIN information_schema.table_constraints tc
|
438
|
+
ON kcu.table_name = tc.table_name
|
439
|
+
AND kcu.table_schema = tc.table_schema
|
440
|
+
AND kcu.constraint_name = tc.constraint_name
|
441
|
+
WHERE constraint_type = 'PRIMARY KEY'
|
442
|
+
AND kcu.table_name = #{quote(name.identifier)}
|
443
|
+
AND kcu.table_schema = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
|
444
|
+
ORDER BY kcu.ordinal_position
|
459
445
|
SQL
|
460
446
|
end
|
461
447
|
|
@@ -490,7 +476,7 @@ module ActiveRecord
|
|
490
476
|
clear_cache!
|
491
477
|
quoted_table_name = quote_table_name(table_name)
|
492
478
|
quoted_column_name = quote_column_name(column_name)
|
493
|
-
sql_type = type_to_sql(type, options
|
479
|
+
sql_type = type_to_sql(type, options)
|
494
480
|
sql = "ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quoted_column_name} TYPE #{sql_type}"
|
495
481
|
if options[:collation]
|
496
482
|
sql << " COLLATE \"#{options[:collation]}\""
|
@@ -498,7 +484,7 @@ module ActiveRecord
|
|
498
484
|
if options[:using]
|
499
485
|
sql << " USING #{options[:using]}"
|
500
486
|
elsif options[:cast_as]
|
501
|
-
cast_as_type = type_to_sql(options[:cast_as], options
|
487
|
+
cast_as_type = type_to_sql(options[:cast_as], options)
|
502
488
|
sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
|
503
489
|
end
|
504
490
|
execute sql
|
@@ -593,7 +579,7 @@ module ActiveRecord
|
|
593
579
|
end
|
594
580
|
|
595
581
|
def foreign_keys(table_name)
|
596
|
-
fk_info = select_all(<<-SQL.strip_heredoc,
|
582
|
+
fk_info = select_all(<<-SQL.strip_heredoc, "SCHEMA")
|
597
583
|
SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
598
584
|
FROM pg_constraint c
|
599
585
|
JOIN pg_class t1 ON c.conrelid = t1.oid
|
@@ -609,70 +595,75 @@ module ActiveRecord
|
|
609
595
|
|
610
596
|
fk_info.map do |row|
|
611
597
|
options = {
|
612
|
-
column: row[
|
613
|
-
name: row[
|
614
|
-
primary_key: row[
|
598
|
+
column: row["column"],
|
599
|
+
name: row["name"],
|
600
|
+
primary_key: row["primary_key"]
|
615
601
|
}
|
616
602
|
|
617
|
-
options[:on_delete] = extract_foreign_key_action(row[
|
618
|
-
options[:on_update] = extract_foreign_key_action(row[
|
603
|
+
options[:on_delete] = extract_foreign_key_action(row["on_delete"])
|
604
|
+
options[:on_update] = extract_foreign_key_action(row["on_update"])
|
619
605
|
|
620
|
-
ForeignKeyDefinition.new(table_name, row[
|
606
|
+
ForeignKeyDefinition.new(table_name, row["to_table"], options)
|
621
607
|
end
|
622
608
|
end
|
623
609
|
|
624
610
|
def extract_foreign_key_action(specifier) # :nodoc:
|
625
611
|
case specifier
|
626
|
-
when
|
627
|
-
when
|
628
|
-
when
|
612
|
+
when "c"; :cascade
|
613
|
+
when "n"; :nullify
|
614
|
+
when "r"; :restrict
|
629
615
|
end
|
630
616
|
end
|
631
617
|
|
618
|
+
def index_name_length
|
619
|
+
63
|
620
|
+
end
|
621
|
+
|
632
622
|
# Maps logical Rails types to PostgreSQL-specific data types.
|
633
|
-
def type_to_sql(type, limit
|
634
|
-
sql =
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
623
|
+
def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **) # :nodoc:
|
624
|
+
sql = \
|
625
|
+
case type.to_s
|
626
|
+
when "binary"
|
627
|
+
# PostgreSQL doesn't support limits on binary (bytea) columns.
|
628
|
+
# The hard limit is 1GB, because of a 32-bit size field, and TOAST.
|
629
|
+
case limit
|
630
|
+
when nil, 0..0x3fffffff; super(type)
|
631
|
+
else raise(ActiveRecordError, "No binary type has byte size #{limit}.")
|
632
|
+
end
|
633
|
+
when "text"
|
634
|
+
# PostgreSQL doesn't support limits on text columns.
|
635
|
+
# The hard limit is 1GB, according to section 8.3 in the manual.
|
636
|
+
case limit
|
637
|
+
when nil, 0..0x3fffffff; super(type)
|
638
|
+
else raise(ActiveRecordError, "The limit on text can be at most 1GB - 1byte.")
|
639
|
+
end
|
640
|
+
when "integer"
|
641
|
+
case limit
|
642
|
+
when 1, 2; "smallint"
|
643
|
+
when nil, 3, 4; "integer"
|
644
|
+
when 5..8; "bigint"
|
645
|
+
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead.")
|
646
|
+
end
|
647
|
+
else
|
648
|
+
super
|
655
649
|
end
|
656
|
-
else
|
657
|
-
super(type, limit, precision, scale)
|
658
|
-
end
|
659
650
|
|
660
|
-
sql <<
|
651
|
+
sql << "[]" if array && type != :primary_key
|
661
652
|
sql
|
662
653
|
end
|
663
654
|
|
664
655
|
# PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and
|
665
656
|
# requires that the ORDER BY include the distinct column.
|
666
657
|
def columns_for_distinct(columns, orders) #:nodoc:
|
667
|
-
order_columns = orders.reject(&:blank?).map{ |s|
|
658
|
+
order_columns = orders.reject(&:blank?).map { |s|
|
668
659
|
# Convert Arel node to string
|
669
660
|
s = s.to_sql unless s.is_a?(String)
|
670
661
|
# Remove any ASC/DESC modifiers
|
671
|
-
s.gsub(/\s+(?:ASC|DESC)\b/i,
|
672
|
-
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i,
|
662
|
+
s.gsub(/\s+(?:ASC|DESC)\b/i, "")
|
663
|
+
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
|
673
664
|
}.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
674
665
|
|
675
|
-
[super, *order_columns].join(
|
666
|
+
[super, *order_columns].join(", ")
|
676
667
|
end
|
677
668
|
|
678
669
|
def fetch_type_metadata(column_name, sql_type, oid, fmod)
|