activerecord 4.1.8 → 4.2.11.3
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 +1165 -1591
- data/README.rdoc +15 -10
- data/lib/active_record/aggregations.rb +15 -8
- data/lib/active_record/association_relation.rb +13 -0
- data/lib/active_record/associations/alias_tracker.rb +3 -12
- data/lib/active_record/associations/association.rb +16 -4
- data/lib/active_record/associations/association_scope.rb +84 -43
- data/lib/active_record/associations/belongs_to_association.rb +28 -10
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -29
- data/lib/active_record/associations/builder/collection_association.rb +5 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +9 -14
- data/lib/active_record/associations/builder/has_many.rb +1 -1
- data/lib/active_record/associations/builder/has_one.rb +2 -2
- data/lib/active_record/associations/builder/singular_association.rb +8 -1
- data/lib/active_record/associations/collection_association.rb +87 -30
- data/lib/active_record/associations/collection_proxy.rb +33 -35
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +83 -22
- data/lib/active_record/associations/has_many_through_association.rb +49 -26
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -15
- data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
- data/lib/active_record/associations/join_dependency.rb +26 -12
- data/lib/active_record/associations/preloader/association.rb +14 -10
- data/lib/active_record/associations/preloader/through_association.rb +4 -3
- data/lib/active_record/associations/preloader.rb +37 -26
- data/lib/active_record/associations/singular_association.rb +17 -2
- data/lib/active_record/associations/through_association.rb +16 -12
- data/lib/active_record/associations.rb +158 -49
- data/lib/active_record/attribute.rb +163 -0
- data/lib/active_record/attribute_assignment.rb +20 -12
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +107 -43
- data/lib/active_record/attribute_methods/primary_key.rb +7 -8
- data/lib/active_record/attribute_methods/query.rb +1 -1
- data/lib/active_record/attribute_methods/read.rb +22 -59
- data/lib/active_record/attribute_methods/serialization.rb +16 -150
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -28
- data/lib/active_record/attribute_methods/write.rb +9 -24
- data/lib/active_record/attribute_methods.rb +57 -95
- data/lib/active_record/attribute_set/builder.rb +106 -0
- data/lib/active_record/attribute_set.rb +81 -0
- data/lib/active_record/attributes.rb +147 -0
- data/lib/active_record/autosave_association.rb +30 -12
- data/lib/active_record/base.rb +13 -24
- data/lib/active_record/callbacks.rb +6 -6
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +85 -53
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +52 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +60 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +39 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +139 -57
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +271 -74
- data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -118
- data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -60
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +295 -141
- data/lib/active_record/connection_adapters/column.rb +29 -240
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -24
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +17 -33
- data/lib/active_record/connection_adapters/mysql_adapter.rb +68 -145
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -25
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -385
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +46 -136
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +134 -43
- data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -477
- data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -75
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +163 -40
- data/lib/active_record/counter_cache.rb +60 -6
- data/lib/active_record/enum.rb +10 -12
- data/lib/active_record/errors.rb +53 -30
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixtures.rb +62 -74
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +35 -10
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/legacy_yaml_adapter.rb +30 -0
- data/lib/active_record/locking/optimistic.rb +46 -26
- data/lib/active_record/migration/command_recorder.rb +19 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +79 -47
- data/lib/active_record/model_schema.rb +52 -58
- data/lib/active_record/nested_attributes.rb +18 -8
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +48 -27
- data/lib/active_record/query_cache.rb +3 -3
- data/lib/active_record/querying.rb +10 -7
- data/lib/active_record/railtie.rb +19 -14
- data/lib/active_record/railties/databases.rake +55 -56
- data/lib/active_record/readonly_attributes.rb +0 -1
- data/lib/active_record/reflection.rb +281 -117
- data/lib/active_record/relation/batches.rb +0 -1
- data/lib/active_record/relation/calculations.rb +41 -37
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +71 -48
- data/lib/active_record/relation/merger.rb +39 -29
- data/lib/active_record/relation/predicate_builder/array_handler.rb +32 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +42 -12
- data/lib/active_record/relation/query_methods.rb +130 -73
- data/lib/active_record/relation/spawn_methods.rb +10 -3
- data/lib/active_record/relation.rb +57 -25
- data/lib/active_record/result.rb +18 -7
- data/lib/active_record/sanitization.rb +12 -2
- data/lib/active_record/schema.rb +0 -1
- data/lib/active_record/schema_dumper.rb +59 -28
- data/lib/active_record/schema_migration.rb +5 -4
- data/lib/active_record/scoping/default.rb +6 -4
- data/lib/active_record/scoping/named.rb +4 -0
- data/lib/active_record/serializers/xml_serializer.rb +3 -7
- data/lib/active_record/statement_cache.rb +95 -10
- data/lib/active_record/store.rb +5 -5
- data/lib/active_record/tasks/database_tasks.rb +61 -8
- data/lib/active_record/tasks/mysql_database_tasks.rb +32 -17
- data/lib/active_record/tasks/postgresql_database_tasks.rb +20 -9
- data/lib/active_record/timestamp.rb +9 -7
- data/lib/active_record/transactions.rb +54 -28
- data/lib/active_record/type/big_integer.rb +13 -0
- data/lib/active_record/type/binary.rb +50 -0
- data/lib/active_record/type/boolean.rb +31 -0
- data/lib/active_record/type/date.rb +50 -0
- data/lib/active_record/type/date_time.rb +54 -0
- data/lib/active_record/type/decimal.rb +64 -0
- data/lib/active_record/type/decimal_without_scale.rb +11 -0
- data/lib/active_record/type/decorator.rb +14 -0
- data/lib/active_record/type/float.rb +19 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
- data/lib/active_record/type/integer.rb +59 -0
- data/lib/active_record/type/mutable.rb +16 -0
- data/lib/active_record/type/numeric.rb +36 -0
- data/lib/active_record/type/serialized.rb +62 -0
- data/lib/active_record/type/string.rb +40 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +26 -0
- data/lib/active_record/type/time_value.rb +38 -0
- data/lib/active_record/type/type_map.rb +64 -0
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type/value.rb +110 -0
- data/lib/active_record/type.rb +23 -0
- data/lib/active_record/validations/associated.rb +5 -3
- data/lib/active_record/validations/presence.rb +5 -3
- data/lib/active_record/validations/uniqueness.rb +24 -20
- data/lib/active_record/validations.rb +25 -19
- data/lib/active_record.rb +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
- metadata +66 -11
- data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -1,16 +1,19 @@
|
|
1
1
|
require 'active_record/connection_adapters/abstract_adapter'
|
2
2
|
require 'active_record/connection_adapters/statement_pool'
|
3
|
+
|
4
|
+
require 'active_record/connection_adapters/postgresql/utils'
|
5
|
+
require 'active_record/connection_adapters/postgresql/column'
|
3
6
|
require 'active_record/connection_adapters/postgresql/oid'
|
4
|
-
require 'active_record/connection_adapters/postgresql/cast'
|
5
|
-
require 'active_record/connection_adapters/postgresql/array_parser'
|
6
7
|
require 'active_record/connection_adapters/postgresql/quoting'
|
8
|
+
require 'active_record/connection_adapters/postgresql/referential_integrity'
|
9
|
+
require 'active_record/connection_adapters/postgresql/schema_definitions'
|
7
10
|
require 'active_record/connection_adapters/postgresql/schema_statements'
|
8
11
|
require 'active_record/connection_adapters/postgresql/database_statements'
|
9
|
-
|
12
|
+
|
10
13
|
require 'arel/visitors/bind_visitor'
|
11
14
|
|
12
15
|
# Make sure we're using pg high enough for PGResult#values
|
13
|
-
gem 'pg', '~> 0.
|
16
|
+
gem 'pg', '~> 0.15'
|
14
17
|
require 'pg'
|
15
18
|
|
16
19
|
require 'ipaddr'
|
@@ -43,222 +46,6 @@ module ActiveRecord
|
|
43
46
|
end
|
44
47
|
|
45
48
|
module ConnectionAdapters
|
46
|
-
# PostgreSQL-specific extensions to column definitions in a table.
|
47
|
-
class PostgreSQLColumn < Column #:nodoc:
|
48
|
-
attr_accessor :array
|
49
|
-
|
50
|
-
def initialize(name, default, oid_type, sql_type = nil, null = true)
|
51
|
-
@oid_type = oid_type
|
52
|
-
default_value = self.class.extract_value_from_default(default)
|
53
|
-
|
54
|
-
if sql_type =~ /\[\]$/
|
55
|
-
@array = true
|
56
|
-
super(name, default_value, sql_type[0..sql_type.length - 3], null)
|
57
|
-
else
|
58
|
-
@array = false
|
59
|
-
super(name, default_value, sql_type, null)
|
60
|
-
end
|
61
|
-
|
62
|
-
@default_function = default if has_default_function?(default_value, default)
|
63
|
-
end
|
64
|
-
|
65
|
-
def number?
|
66
|
-
!array && super
|
67
|
-
end
|
68
|
-
|
69
|
-
def text?
|
70
|
-
!array && super
|
71
|
-
end
|
72
|
-
|
73
|
-
# :stopdoc:
|
74
|
-
class << self
|
75
|
-
include ConnectionAdapters::PostgreSQLColumn::Cast
|
76
|
-
include ConnectionAdapters::PostgreSQLColumn::ArrayParser
|
77
|
-
attr_accessor :money_precision
|
78
|
-
end
|
79
|
-
# :startdoc:
|
80
|
-
|
81
|
-
# Extracts the value from a PostgreSQL column default definition.
|
82
|
-
def self.extract_value_from_default(default)
|
83
|
-
# This is a performance optimization for Ruby 1.9.2 in development.
|
84
|
-
# If the value is nil, we return nil straight away without checking
|
85
|
-
# the regular expressions. If we check each regular expression,
|
86
|
-
# Regexp#=== will call NilClass#to_str, which will trigger
|
87
|
-
# method_missing (defined by whiny nil in ActiveSupport) which
|
88
|
-
# makes this method very very slow.
|
89
|
-
return default unless default
|
90
|
-
|
91
|
-
case default
|
92
|
-
when /\A'(.*)'::(num|date|tstz|ts|int4|int8)range\z/m
|
93
|
-
$1
|
94
|
-
# Numeric types
|
95
|
-
when /\A\(?(-?\d+(\.\d*)?\)?(::bigint)?)\z/
|
96
|
-
$1
|
97
|
-
# Character types
|
98
|
-
when /\A\(?'(.*)'::.*\b(?:character varying|bpchar|text)\z/m
|
99
|
-
$1.gsub(/''/, "'")
|
100
|
-
# Binary data types
|
101
|
-
when /\A'(.*)'::bytea\z/m
|
102
|
-
$1
|
103
|
-
# Date/time types
|
104
|
-
when /\A'(.+)'::(?:time(?:stamp)? with(?:out)? time zone|date)\z/
|
105
|
-
$1
|
106
|
-
when /\A'(.*)'::interval\z/
|
107
|
-
$1
|
108
|
-
# Boolean type
|
109
|
-
when 'true'
|
110
|
-
true
|
111
|
-
when 'false'
|
112
|
-
false
|
113
|
-
# Geometric types
|
114
|
-
when /\A'(.*)'::(?:point|line|lseg|box|"?path"?|polygon|circle)\z/
|
115
|
-
$1
|
116
|
-
# Network address types
|
117
|
-
when /\A'(.*)'::(?:cidr|inet|macaddr)\z/
|
118
|
-
$1
|
119
|
-
# Bit string types
|
120
|
-
when /\AB'(.*)'::"?bit(?: varying)?"?\z/
|
121
|
-
$1
|
122
|
-
# XML type
|
123
|
-
when /\A'(.*)'::xml\z/m
|
124
|
-
$1
|
125
|
-
# Arrays
|
126
|
-
when /\A'(.*)'::"?\D+"?\[\]\z/
|
127
|
-
$1
|
128
|
-
# Hstore
|
129
|
-
when /\A'(.*)'::hstore\z/
|
130
|
-
$1
|
131
|
-
# JSON
|
132
|
-
when /\A'(.*)'::json\z/
|
133
|
-
$1
|
134
|
-
# Object identifier types
|
135
|
-
when /\A-?\d+\z/
|
136
|
-
$1
|
137
|
-
else
|
138
|
-
# Anything else is blank, some user type, or some function
|
139
|
-
# and we can't know the value of that, so return nil.
|
140
|
-
nil
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def type_cast_for_write(value)
|
145
|
-
if @oid_type.respond_to?(:type_cast_for_write)
|
146
|
-
@oid_type.type_cast_for_write(value)
|
147
|
-
else
|
148
|
-
super
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def type_cast(value)
|
153
|
-
return if value.nil?
|
154
|
-
return super if encoded?
|
155
|
-
|
156
|
-
@oid_type.type_cast value
|
157
|
-
end
|
158
|
-
|
159
|
-
def accessor
|
160
|
-
@oid_type.accessor
|
161
|
-
end
|
162
|
-
|
163
|
-
private
|
164
|
-
|
165
|
-
def has_default_function?(default_value, default)
|
166
|
-
!default_value && (%r{\w+\(.*\)} === default)
|
167
|
-
end
|
168
|
-
|
169
|
-
def extract_limit(sql_type)
|
170
|
-
case sql_type
|
171
|
-
when /^bigint/i; 8
|
172
|
-
when /^smallint/i; 2
|
173
|
-
when /^timestamp/i; nil
|
174
|
-
else super
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
# Extracts the scale from PostgreSQL-specific data types.
|
179
|
-
def extract_scale(sql_type)
|
180
|
-
# Money type has a fixed scale of 2.
|
181
|
-
sql_type =~ /^money/ ? 2 : super
|
182
|
-
end
|
183
|
-
|
184
|
-
# Extracts the precision from PostgreSQL-specific data types.
|
185
|
-
def extract_precision(sql_type)
|
186
|
-
if sql_type == 'money'
|
187
|
-
self.class.money_precision
|
188
|
-
elsif sql_type =~ /timestamp/i
|
189
|
-
$1.to_i if sql_type =~ /\((\d+)\)/
|
190
|
-
else
|
191
|
-
super
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
# Maps PostgreSQL-specific data types to logical Rails types.
|
196
|
-
def simplified_type(field_type)
|
197
|
-
case field_type
|
198
|
-
# Numeric and monetary types
|
199
|
-
when /^(?:real|double precision)$/
|
200
|
-
:float
|
201
|
-
# Monetary types
|
202
|
-
when 'money'
|
203
|
-
:decimal
|
204
|
-
when 'hstore'
|
205
|
-
:hstore
|
206
|
-
when 'ltree'
|
207
|
-
:ltree
|
208
|
-
# Network address types
|
209
|
-
when 'inet'
|
210
|
-
:inet
|
211
|
-
when 'cidr'
|
212
|
-
:cidr
|
213
|
-
when 'macaddr'
|
214
|
-
:macaddr
|
215
|
-
# Character types
|
216
|
-
when /^(?:character varying|bpchar)(?:\(\d+\))?$/
|
217
|
-
:string
|
218
|
-
# Binary data types
|
219
|
-
when 'bytea'
|
220
|
-
:binary
|
221
|
-
# Date/time types
|
222
|
-
when /^timestamp with(?:out)? time zone$/
|
223
|
-
:datetime
|
224
|
-
when /^interval(?:|\(\d+\))$/
|
225
|
-
:string
|
226
|
-
# Geometric types
|
227
|
-
when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/
|
228
|
-
:string
|
229
|
-
# Bit strings
|
230
|
-
when /^bit(?: varying)?(?:\(\d+\))?$/
|
231
|
-
:string
|
232
|
-
# XML type
|
233
|
-
when 'xml'
|
234
|
-
:xml
|
235
|
-
# tsvector type
|
236
|
-
when 'tsvector'
|
237
|
-
:tsvector
|
238
|
-
# Arrays
|
239
|
-
when /^\D+\[\]$/
|
240
|
-
:string
|
241
|
-
# Object identifier types
|
242
|
-
when 'oid'
|
243
|
-
:integer
|
244
|
-
# UUID type
|
245
|
-
when 'uuid'
|
246
|
-
:uuid
|
247
|
-
# JSON type
|
248
|
-
when 'json'
|
249
|
-
:json
|
250
|
-
# Small and big integer types
|
251
|
-
when /^(?:small|big)int$/
|
252
|
-
:integer
|
253
|
-
when /(num|date|tstz|ts|int4|int8)range$/
|
254
|
-
field_type.to_sym
|
255
|
-
# Pass through all types that are not specific to PostgreSQL.
|
256
|
-
else
|
257
|
-
super
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
49
|
# The PostgreSQL adapter works with the native C (https://bitbucket.org/ged/ruby-pg) driver.
|
263
50
|
#
|
264
51
|
# Options:
|
@@ -277,7 +64,7 @@ module ActiveRecord
|
|
277
64
|
# <tt>SET client_min_messages TO <min_messages></tt> call on the connection.
|
278
65
|
# * <tt>:variables</tt> - An optional hash of additional parameters that
|
279
66
|
# will be used in <tt>SET SESSION key = val</tt> calls on the connection.
|
280
|
-
# * <tt>:insert_returning</tt> - An optional boolean to control the use
|
67
|
+
# * <tt>:insert_returning</tt> - An optional boolean to control the use of <tt>RETURNING</tt> for <tt>INSERT</tt> statements
|
281
68
|
# defaults to true.
|
282
69
|
#
|
283
70
|
# Any further options are used as connection parameters to libpq. See
|
@@ -287,142 +74,17 @@ module ActiveRecord
|
|
287
74
|
# In addition, default connection parameters of libpq can be set per environment variables.
|
288
75
|
# See http://www.postgresql.org/docs/9.1/static/libpq-envars.html .
|
289
76
|
class PostgreSQLAdapter < AbstractAdapter
|
290
|
-
|
291
|
-
attr_accessor :array
|
292
|
-
end
|
293
|
-
|
294
|
-
module ColumnMethods
|
295
|
-
def xml(*args)
|
296
|
-
options = args.extract_options!
|
297
|
-
column(args[0], 'xml', options)
|
298
|
-
end
|
299
|
-
|
300
|
-
def tsvector(*args)
|
301
|
-
options = args.extract_options!
|
302
|
-
column(args[0], 'tsvector', options)
|
303
|
-
end
|
304
|
-
|
305
|
-
def int4range(name, options = {})
|
306
|
-
column(name, 'int4range', options)
|
307
|
-
end
|
308
|
-
|
309
|
-
def int8range(name, options = {})
|
310
|
-
column(name, 'int8range', options)
|
311
|
-
end
|
312
|
-
|
313
|
-
def tsrange(name, options = {})
|
314
|
-
column(name, 'tsrange', options)
|
315
|
-
end
|
316
|
-
|
317
|
-
def tstzrange(name, options = {})
|
318
|
-
column(name, 'tstzrange', options)
|
319
|
-
end
|
320
|
-
|
321
|
-
def numrange(name, options = {})
|
322
|
-
column(name, 'numrange', options)
|
323
|
-
end
|
324
|
-
|
325
|
-
def daterange(name, options = {})
|
326
|
-
column(name, 'daterange', options)
|
327
|
-
end
|
328
|
-
|
329
|
-
def hstore(name, options = {})
|
330
|
-
column(name, 'hstore', options)
|
331
|
-
end
|
332
|
-
|
333
|
-
def ltree(name, options = {})
|
334
|
-
column(name, 'ltree', options)
|
335
|
-
end
|
336
|
-
|
337
|
-
def inet(name, options = {})
|
338
|
-
column(name, 'inet', options)
|
339
|
-
end
|
340
|
-
|
341
|
-
def cidr(name, options = {})
|
342
|
-
column(name, 'cidr', options)
|
343
|
-
end
|
344
|
-
|
345
|
-
def macaddr(name, options = {})
|
346
|
-
column(name, 'macaddr', options)
|
347
|
-
end
|
348
|
-
|
349
|
-
def uuid(name, options = {})
|
350
|
-
column(name, 'uuid', options)
|
351
|
-
end
|
352
|
-
|
353
|
-
def json(name, options = {})
|
354
|
-
column(name, 'json', options)
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
359
|
-
include ColumnMethods
|
360
|
-
|
361
|
-
# Defines the primary key field.
|
362
|
-
# Use of the native PostgreSQL UUID type is supported, and can be used
|
363
|
-
# by defining your tables as such:
|
364
|
-
#
|
365
|
-
# create_table :stuffs, id: :uuid do |t|
|
366
|
-
# t.string :content
|
367
|
-
# t.timestamps
|
368
|
-
# end
|
369
|
-
#
|
370
|
-
# By default, this will use the +uuid_generate_v4()+ function from the
|
371
|
-
# +uuid-ossp+ extension, which MUST be enabled on your database. To enable
|
372
|
-
# the +uuid-ossp+ extension, you can use the +enable_extension+ method in your
|
373
|
-
# migrations. To use a UUID primary key without +uuid-ossp+ enabled, you can
|
374
|
-
# set the +:default+ option to +nil+:
|
375
|
-
#
|
376
|
-
# create_table :stuffs, id: false do |t|
|
377
|
-
# t.primary_key :id, :uuid, default: nil
|
378
|
-
# t.uuid :foo_id
|
379
|
-
# t.timestamps
|
380
|
-
# end
|
381
|
-
#
|
382
|
-
# You may also pass a different UUID generation function from +uuid-ossp+
|
383
|
-
# or another library.
|
384
|
-
#
|
385
|
-
# Note that setting the UUID primary key default value to +nil+ will
|
386
|
-
# require you to assure that you always provide a UUID value before saving
|
387
|
-
# a record (as primary keys cannot be +nil+). This might be done via the
|
388
|
-
# +SecureRandom.uuid+ method and a +before_save+ callback, for instance.
|
389
|
-
def primary_key(name, type = :primary_key, options = {})
|
390
|
-
return super unless type == :uuid
|
391
|
-
options[:default] = options.fetch(:default, 'uuid_generate_v4()')
|
392
|
-
options[:primary_key] = true
|
393
|
-
column name, type, options
|
394
|
-
end
|
395
|
-
|
396
|
-
def column(name, type = nil, options = {})
|
397
|
-
super
|
398
|
-
column = self[name]
|
399
|
-
column.array = options[:array]
|
400
|
-
|
401
|
-
self
|
402
|
-
end
|
403
|
-
|
404
|
-
private
|
405
|
-
|
406
|
-
def create_column_definition(name, type)
|
407
|
-
ColumnDefinition.new name, type
|
408
|
-
end
|
409
|
-
end
|
410
|
-
|
411
|
-
class Table < ActiveRecord::ConnectionAdapters::Table
|
412
|
-
include ColumnMethods
|
413
|
-
end
|
414
|
-
|
415
|
-
ADAPTER_NAME = 'PostgreSQL'
|
77
|
+
ADAPTER_NAME = 'PostgreSQL'.freeze
|
416
78
|
|
417
79
|
NATIVE_DATABASE_TYPES = {
|
418
80
|
primary_key: "serial primary key",
|
419
|
-
|
81
|
+
bigserial: "bigserial",
|
82
|
+
string: { name: "character varying" },
|
420
83
|
text: { name: "text" },
|
421
84
|
integer: { name: "integer" },
|
422
85
|
float: { name: "float" },
|
423
86
|
decimal: { name: "decimal" },
|
424
87
|
datetime: { name: "timestamp" },
|
425
|
-
timestamp: { name: "timestamp" },
|
426
88
|
time: { name: "time" },
|
427
89
|
date: { name: "date" },
|
428
90
|
daterange: { name: "daterange" },
|
@@ -433,6 +95,7 @@ module ActiveRecord
|
|
433
95
|
int8range: { name: "int8range" },
|
434
96
|
binary: { name: "bytea" },
|
435
97
|
boolean: { name: "boolean" },
|
98
|
+
bigint: { name: "bigint" },
|
436
99
|
xml: { name: "xml" },
|
437
100
|
tsvector: { name: "tsvector" },
|
438
101
|
hstore: { name: "hstore" },
|
@@ -441,30 +104,37 @@ module ActiveRecord
|
|
441
104
|
macaddr: { name: "macaddr" },
|
442
105
|
uuid: { name: "uuid" },
|
443
106
|
json: { name: "json" },
|
444
|
-
|
107
|
+
jsonb: { name: "jsonb" },
|
108
|
+
ltree: { name: "ltree" },
|
109
|
+
citext: { name: "citext" },
|
110
|
+
point: { name: "point" },
|
111
|
+
bit: { name: "bit" },
|
112
|
+
bit_varying: { name: "bit varying" },
|
113
|
+
money: { name: "money" },
|
445
114
|
}
|
446
115
|
|
447
|
-
|
448
|
-
|
449
|
-
include
|
450
|
-
include
|
116
|
+
OID = PostgreSQL::OID #:nodoc:
|
117
|
+
|
118
|
+
include PostgreSQL::Quoting
|
119
|
+
include PostgreSQL::ReferentialIntegrity
|
120
|
+
include PostgreSQL::SchemaStatements
|
121
|
+
include PostgreSQL::DatabaseStatements
|
451
122
|
include Savepoints
|
452
123
|
|
453
|
-
|
454
|
-
|
455
|
-
ADAPTER_NAME
|
124
|
+
def schema_creation # :nodoc:
|
125
|
+
PostgreSQL::SchemaCreation.new self
|
456
126
|
end
|
457
127
|
|
458
|
-
# Adds
|
128
|
+
# Adds +:array+ option to the default set provided by the
|
459
129
|
# AbstractAdapter
|
460
|
-
def prepare_column_options(column, types)
|
130
|
+
def prepare_column_options(column, types) # :nodoc:
|
461
131
|
spec = super
|
462
132
|
spec[:array] = 'true' if column.respond_to?(:array) && column.array
|
463
133
|
spec[:default] = "\"#{column.default_function}\"" if column.default_function
|
464
134
|
spec
|
465
135
|
end
|
466
136
|
|
467
|
-
# Adds
|
137
|
+
# Adds +:array+ as a valid migration key
|
468
138
|
def migration_keys
|
469
139
|
super + [:array]
|
470
140
|
end
|
@@ -487,6 +157,14 @@ module ActiveRecord
|
|
487
157
|
true
|
488
158
|
end
|
489
159
|
|
160
|
+
def supports_foreign_keys?
|
161
|
+
true
|
162
|
+
end
|
163
|
+
|
164
|
+
def supports_views?
|
165
|
+
true
|
166
|
+
end
|
167
|
+
|
490
168
|
def index_algorithms
|
491
169
|
{ concurrently: 'CONCURRENTLY' }
|
492
170
|
end
|
@@ -544,19 +222,15 @@ module ActiveRecord
|
|
544
222
|
end
|
545
223
|
end
|
546
224
|
|
547
|
-
class BindSubstitution < Arel::Visitors::PostgreSQL # :nodoc:
|
548
|
-
include Arel::Visitors::BindVisitor
|
549
|
-
end
|
550
|
-
|
551
225
|
# Initializes and connects a PostgreSQL adapter.
|
552
226
|
def initialize(connection, logger, connection_parameters, config)
|
553
227
|
super(connection, logger)
|
554
228
|
|
229
|
+
@visitor = Arel::Visitors::PostgreSQL.new self
|
555
230
|
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
556
231
|
@prepared_statements = true
|
557
|
-
@visitor = Arel::Visitors::PostgreSQL.new self
|
558
232
|
else
|
559
|
-
@
|
233
|
+
@prepared_statements = false
|
560
234
|
end
|
561
235
|
|
562
236
|
@connection_parameters, @config = connection_parameters, config
|
@@ -573,7 +247,7 @@ module ActiveRecord
|
|
573
247
|
raise "Your version of PostgreSQL (#{postgresql_version}) is too old, please upgrade!"
|
574
248
|
end
|
575
249
|
|
576
|
-
@type_map =
|
250
|
+
@type_map = Type::HashLookupTypeMap.new
|
577
251
|
initialize_type_map(type_map)
|
578
252
|
@local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"]
|
579
253
|
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
|
@@ -584,6 +258,10 @@ module ActiveRecord
|
|
584
258
|
@statements.clear
|
585
259
|
end
|
586
260
|
|
261
|
+
def truncate(table_name, name = nil)
|
262
|
+
exec_query "TRUNCATE TABLE #{quote_table_name(table_name)}", name, []
|
263
|
+
end
|
264
|
+
|
587
265
|
# Is this connection alive and ready for queries?
|
588
266
|
def active?
|
589
267
|
@connection.query 'SELECT 1'
|
@@ -592,10 +270,6 @@ module ActiveRecord
|
|
592
270
|
false
|
593
271
|
end
|
594
272
|
|
595
|
-
def active_threadsafe?
|
596
|
-
@connection.connect_poll != PG::PGRES_POLLING_FAILED
|
597
|
-
end
|
598
|
-
|
599
273
|
# Close then reopen the connection.
|
600
274
|
def reconnect!
|
601
275
|
super
|
@@ -605,7 +279,12 @@ module ActiveRecord
|
|
605
279
|
|
606
280
|
def reset!
|
607
281
|
clear_cache!
|
608
|
-
|
282
|
+
reset_transaction
|
283
|
+
unless @connection.transaction_status == ::PG::PQTRANS_IDLE
|
284
|
+
@connection.query 'ROLLBACK'
|
285
|
+
end
|
286
|
+
@connection.query 'DISCARD ALL'
|
287
|
+
configure_connection
|
609
288
|
end
|
610
289
|
|
611
290
|
# Disconnects from the database if already connected. Otherwise, this
|
@@ -629,16 +308,8 @@ module ActiveRecord
|
|
629
308
|
true
|
630
309
|
end
|
631
310
|
|
632
|
-
# Enable standard-conforming strings if available.
|
633
311
|
def set_standard_conforming_strings
|
634
|
-
|
635
|
-
execute('SET standard_conforming_strings = on', 'SCHEMA') rescue nil
|
636
|
-
ensure
|
637
|
-
self.client_min_messages = old
|
638
|
-
end
|
639
|
-
|
640
|
-
def supports_insert_with_returning?
|
641
|
-
true
|
312
|
+
execute('SET standard_conforming_strings = on', 'SCHEMA')
|
642
313
|
end
|
643
314
|
|
644
315
|
def supports_ddl_transactions?
|
@@ -659,6 +330,10 @@ module ActiveRecord
|
|
659
330
|
postgresql_version >= 90200
|
660
331
|
end
|
661
332
|
|
333
|
+
def supports_materialized_views?
|
334
|
+
postgresql_version >= 90300
|
335
|
+
end
|
336
|
+
|
662
337
|
def enable_extension(name)
|
663
338
|
exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
|
664
339
|
reload_type_map
|
@@ -675,14 +350,13 @@ module ActiveRecord
|
|
675
350
|
if supports_extensions?
|
676
351
|
res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled",
|
677
352
|
'SCHEMA'
|
678
|
-
res.
|
353
|
+
res.cast_values.first
|
679
354
|
end
|
680
355
|
end
|
681
356
|
|
682
357
|
def extensions
|
683
358
|
if supports_extensions?
|
684
|
-
|
685
|
-
res.rows.map { |r| res.column_types['extname'].type_cast r.first }
|
359
|
+
exec_query("SELECT extname from pg_extension", "SCHEMA").cast_values
|
686
360
|
else
|
687
361
|
super
|
688
362
|
end
|
@@ -699,25 +373,6 @@ module ActiveRecord
|
|
699
373
|
exec_query "SET SESSION AUTHORIZATION #{user}"
|
700
374
|
end
|
701
375
|
|
702
|
-
module Utils
|
703
|
-
extend self
|
704
|
-
|
705
|
-
# Returns an array of <tt>[schema_name, table_name]</tt> extracted from +name+.
|
706
|
-
# +schema_name+ is nil if not specified in +name+.
|
707
|
-
# +schema_name+ and +table_name+ exclude surrounding quotes (regardless of whether provided in +name+)
|
708
|
-
# +name+ supports the range of schema/table references understood by PostgreSQL, for example:
|
709
|
-
#
|
710
|
-
# * <tt>table_name</tt>
|
711
|
-
# * <tt>"table.name"</tt>
|
712
|
-
# * <tt>schema_name.table_name</tt>
|
713
|
-
# * <tt>schema_name."table.name"</tt>
|
714
|
-
# * <tt>"schema.name"."table name"</tt>
|
715
|
-
def extract_schema_and_table(name)
|
716
|
-
table, schema = name.scan(/[^".\s]+|"[^"]*"/)[0..1].collect{|m| m.gsub(/(^"|"$)/,'') }.reverse
|
717
|
-
[schema, table]
|
718
|
-
end
|
719
|
-
end
|
720
|
-
|
721
376
|
def use_insert_returning?
|
722
377
|
@use_insert_returning
|
723
378
|
end
|
@@ -727,9 +382,24 @@ module ActiveRecord
|
|
727
382
|
end
|
728
383
|
|
729
384
|
def update_table_definition(table_name, base) #:nodoc:
|
730
|
-
Table.new(table_name, base)
|
385
|
+
PostgreSQL::Table.new(table_name, base)
|
386
|
+
end
|
387
|
+
|
388
|
+
def lookup_cast_type(sql_type) # :nodoc:
|
389
|
+
oid = execute("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").first['oid'].to_i
|
390
|
+
super(oid)
|
391
|
+
end
|
392
|
+
|
393
|
+
def column_name_for_operation(operation, node) # :nodoc:
|
394
|
+
OPERATION_ALIASES.fetch(operation) { operation.downcase }
|
731
395
|
end
|
732
396
|
|
397
|
+
OPERATION_ALIASES = { # :nodoc:
|
398
|
+
"maximum" => "max",
|
399
|
+
"minimum" => "min",
|
400
|
+
"average" => "avg",
|
401
|
+
}
|
402
|
+
|
733
403
|
protected
|
734
404
|
|
735
405
|
# Returns the version of the connected PostgreSQL server.
|
@@ -756,68 +426,168 @@ module ActiveRecord
|
|
756
426
|
|
757
427
|
private
|
758
428
|
|
759
|
-
def
|
760
|
-
|
761
|
-
|
429
|
+
def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
|
430
|
+
if !type_map.key?(oid)
|
431
|
+
load_additional_types(type_map, [oid])
|
432
|
+
end
|
762
433
|
|
763
|
-
|
764
|
-
type_map.fetch(oid, fmod) {
|
434
|
+
type_map.fetch(oid, fmod, sql_type) {
|
765
435
|
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
|
766
|
-
|
436
|
+
Type::Value.new.tap do |cast_type|
|
437
|
+
type_map.register_type(oid, cast_type)
|
438
|
+
end
|
767
439
|
}
|
768
440
|
end
|
769
441
|
|
770
|
-
def
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
442
|
+
def initialize_type_map(m) # :nodoc:
|
443
|
+
register_class_with_limit m, 'int2', OID::Integer
|
444
|
+
register_class_with_limit m, 'int4', OID::Integer
|
445
|
+
register_class_with_limit m, 'int8', OID::Integer
|
446
|
+
m.alias_type 'oid', 'int2'
|
447
|
+
m.register_type 'float4', OID::Float.new
|
448
|
+
m.alias_type 'float8', 'float4'
|
449
|
+
m.register_type 'text', Type::Text.new
|
450
|
+
register_class_with_limit m, 'varchar', Type::String
|
451
|
+
m.alias_type 'char', 'varchar'
|
452
|
+
m.alias_type 'name', 'varchar'
|
453
|
+
m.alias_type 'bpchar', 'varchar'
|
454
|
+
m.register_type 'bool', Type::Boolean.new
|
455
|
+
register_class_with_limit m, 'bit', OID::Bit
|
456
|
+
register_class_with_limit m, 'varbit', OID::BitVarying
|
457
|
+
m.alias_type 'timestamptz', 'timestamp'
|
458
|
+
m.register_type 'date', OID::Date.new
|
459
|
+
m.register_type 'time', OID::Time.new
|
460
|
+
|
461
|
+
m.register_type 'money', OID::Money.new
|
462
|
+
m.register_type 'bytea', OID::Bytea.new
|
463
|
+
m.register_type 'point', OID::Point.new
|
464
|
+
m.register_type 'hstore', OID::Hstore.new
|
465
|
+
m.register_type 'json', OID::Json.new
|
466
|
+
m.register_type 'jsonb', OID::Jsonb.new
|
467
|
+
m.register_type 'cidr', OID::Cidr.new
|
468
|
+
m.register_type 'inet', OID::Inet.new
|
469
|
+
m.register_type 'uuid', OID::Uuid.new
|
470
|
+
m.register_type 'xml', OID::Xml.new
|
471
|
+
m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
|
472
|
+
m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
|
473
|
+
m.register_type 'citext', OID::SpecializedString.new(:citext)
|
474
|
+
m.register_type 'ltree', OID::SpecializedString.new(:ltree)
|
475
|
+
|
476
|
+
# FIXME: why are we keeping these types as strings?
|
477
|
+
m.alias_type 'interval', 'varchar'
|
478
|
+
m.alias_type 'path', 'varchar'
|
479
|
+
m.alias_type 'line', 'varchar'
|
480
|
+
m.alias_type 'polygon', 'varchar'
|
481
|
+
m.alias_type 'circle', 'varchar'
|
482
|
+
m.alias_type 'lseg', 'varchar'
|
483
|
+
m.alias_type 'box', 'varchar'
|
484
|
+
|
485
|
+
m.register_type 'timestamp' do |_, _, sql_type|
|
486
|
+
precision = extract_precision(sql_type)
|
487
|
+
OID::DateTime.new(precision: precision)
|
488
|
+
end
|
777
489
|
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
#
|
783
|
-
|
784
|
-
|
490
|
+
m.register_type 'numeric' do |_, fmod, sql_type|
|
491
|
+
precision = extract_precision(sql_type)
|
492
|
+
scale = extract_scale(sql_type)
|
493
|
+
|
494
|
+
# The type for the numeric depends on the width of the field,
|
495
|
+
# so we'll do something special here.
|
496
|
+
#
|
497
|
+
# When dealing with decimal columns:
|
498
|
+
#
|
499
|
+
# places after decimal = fmod - 4 & 0xffff
|
500
|
+
# places before decimal = (fmod - 4) >> 16 & 0xffff
|
501
|
+
if fmod && (fmod - 4 & 0xffff).zero?
|
502
|
+
# FIXME: Remove this class, and the second argument to
|
503
|
+
# lookups on PG
|
504
|
+
Type::DecimalWithoutScale.new(precision: precision)
|
505
|
+
else
|
506
|
+
OID::Decimal.new(precision: precision, scale: scale)
|
785
507
|
end
|
786
|
-
|
787
|
-
vector = OID::Vector.new row['typdelim'], type_map[row['typelem'].to_i]
|
788
508
|
end
|
789
509
|
|
790
|
-
|
791
|
-
type_map
|
510
|
+
load_additional_types(m)
|
792
511
|
end
|
793
512
|
|
794
|
-
def
|
795
|
-
|
796
|
-
|
513
|
+
def extract_limit(sql_type) # :nodoc:
|
514
|
+
case sql_type
|
515
|
+
when /^bigint/i, /^int8/i
|
516
|
+
8
|
517
|
+
when /^smallint/i
|
518
|
+
2
|
519
|
+
else
|
520
|
+
super
|
521
|
+
end
|
522
|
+
end
|
797
523
|
|
798
|
-
|
799
|
-
|
800
|
-
|
524
|
+
# Extracts the value from a PostgreSQL column default definition.
|
525
|
+
def extract_value_from_default(oid, default) # :nodoc:
|
526
|
+
case default
|
527
|
+
# Quoted types
|
528
|
+
when /\A[\(B]?'(.*)'::/m
|
529
|
+
$1.gsub(/''/, "'")
|
530
|
+
# Boolean types
|
531
|
+
when 'true', 'false'
|
532
|
+
default
|
533
|
+
# Numeric types
|
534
|
+
when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
|
535
|
+
$1
|
536
|
+
# Object identifier types
|
537
|
+
when /\A-?\d+\z/
|
538
|
+
$1
|
539
|
+
else
|
540
|
+
# Anything else is blank, some user type, or some function
|
541
|
+
# and we can't know the value of that, so return nil.
|
542
|
+
nil
|
801
543
|
end
|
544
|
+
end
|
545
|
+
|
546
|
+
def extract_default_function(default_value, default) # :nodoc:
|
547
|
+
default if has_default_function?(default_value, default)
|
548
|
+
end
|
549
|
+
|
550
|
+
def has_default_function?(default_value, default) # :nodoc:
|
551
|
+
!default_value && (%r{\w+\(.*\)} === default)
|
552
|
+
end
|
802
553
|
|
803
|
-
|
554
|
+
def load_additional_types(type_map, oids = nil) # :nodoc:
|
555
|
+
initializer = OID::TypeMapInitializer.new(type_map)
|
804
556
|
|
805
|
-
|
557
|
+
if supports_ranges?
|
558
|
+
query = <<-SQL
|
559
|
+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
|
560
|
+
FROM pg_type as t
|
561
|
+
LEFT JOIN pg_range as r ON oid = rngtypid
|
562
|
+
SQL
|
563
|
+
else
|
564
|
+
query = <<-SQL
|
565
|
+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
|
566
|
+
FROM pg_type as t
|
567
|
+
SQL
|
568
|
+
end
|
806
569
|
|
807
|
-
|
808
|
-
|
809
|
-
|
570
|
+
if oids
|
571
|
+
query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
|
572
|
+
else
|
573
|
+
query += initializer.query_conditions_for_initial_load(type_map)
|
810
574
|
end
|
811
575
|
|
812
|
-
|
813
|
-
|
814
|
-
array = OID::Array.new type_map[row['typelem'].to_i]
|
815
|
-
type_map[row['oid'].to_i] = array
|
576
|
+
execute_and_clear(query, 'SCHEMA', []) do |records|
|
577
|
+
initializer.run(records)
|
816
578
|
end
|
817
579
|
end
|
818
580
|
|
819
581
|
FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
|
820
582
|
|
583
|
+
def execute_and_clear(sql, name, binds)
|
584
|
+
result = without_prepared_statement?(binds) ? exec_no_cache(sql, name, binds) :
|
585
|
+
exec_cache(sql, name, binds)
|
586
|
+
ret = yield result
|
587
|
+
result.clear
|
588
|
+
ret
|
589
|
+
end
|
590
|
+
|
821
591
|
def exec_no_cache(sql, name, binds)
|
822
592
|
log(sql, name, binds) { @connection.async_exec(sql, []) }
|
823
593
|
end
|
@@ -829,9 +599,7 @@ module ActiveRecord
|
|
829
599
|
}
|
830
600
|
|
831
601
|
log(sql, name, type_casted_binds, stmt_key) do
|
832
|
-
@connection.
|
833
|
-
@connection.block
|
834
|
-
@connection.get_last_result
|
602
|
+
@connection.exec_prepared(stmt_key, type_casted_binds.map { |_, val| val })
|
835
603
|
end
|
836
604
|
rescue ActiveRecord::StatementInvalid => e
|
837
605
|
pgerror = e.original_exception
|
@@ -877,11 +645,6 @@ module ActiveRecord
|
|
877
645
|
@statements[sql_key]
|
878
646
|
end
|
879
647
|
|
880
|
-
# The internal PostgreSQL identifier of the money data type.
|
881
|
-
MONEY_COLUMN_TYPE_OID = 790 #:nodoc:
|
882
|
-
# The internal PostgreSQL identifier of the BYTEA data type.
|
883
|
-
BYTEA_COLUMN_TYPE_OID = 17 #:nodoc:
|
884
|
-
|
885
648
|
# Connects to a PostgreSQL server and sets up the adapter depending on the
|
886
649
|
# connected server's characteristics.
|
887
650
|
def connect
|
@@ -890,14 +653,14 @@ module ActiveRecord
|
|
890
653
|
# Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of
|
891
654
|
# PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision
|
892
655
|
# should know about this but can't detect it there, so deal with it here.
|
893
|
-
|
656
|
+
OID::Money.precision = (postgresql_version >= 80300) ? 19 : 10
|
894
657
|
|
895
658
|
configure_connection
|
896
659
|
rescue ::PG::Error => error
|
897
660
|
if error.message.include?("does not exist")
|
898
|
-
raise ActiveRecord::NoDatabaseError.new(error.message)
|
661
|
+
raise ActiveRecord::NoDatabaseError.new(error.message, error)
|
899
662
|
else
|
900
|
-
raise
|
663
|
+
raise
|
901
664
|
end
|
902
665
|
end
|
903
666
|
|
@@ -910,7 +673,7 @@ module ActiveRecord
|
|
910
673
|
self.client_min_messages = @config[:min_messages] || 'warning'
|
911
674
|
self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
|
912
675
|
|
913
|
-
# Use standard-conforming strings
|
676
|
+
# Use standard-conforming strings so we don't have to do the E'...' dance.
|
914
677
|
set_standard_conforming_strings
|
915
678
|
|
916
679
|
# If using Active Record's time zone support configure the connection to return
|
@@ -928,9 +691,9 @@ module ActiveRecord
|
|
928
691
|
variables.map do |k, v|
|
929
692
|
if v == ':default' || v == :default
|
930
693
|
# Sets the value to the global or compile default
|
931
|
-
execute("SET SESSION #{k
|
694
|
+
execute("SET SESSION #{k} TO DEFAULT", 'SCHEMA')
|
932
695
|
elsif !v.nil?
|
933
|
-
execute("SET SESSION #{k
|
696
|
+
execute("SET SESSION #{k} TO #{quote(v)}", 'SCHEMA')
|
934
697
|
end
|
935
698
|
end
|
936
699
|
end
|
@@ -948,12 +711,6 @@ module ActiveRecord
|
|
948
711
|
exec_query("SELECT currval('#{sequence_name}')", 'SQL')
|
949
712
|
end
|
950
713
|
|
951
|
-
# Executes a SELECT query and returns the results, performing any data type
|
952
|
-
# conversions that are required to be performed here instead of in PostgreSQLColumn.
|
953
|
-
def select(sql, name = nil, binds = [])
|
954
|
-
exec_query(sql, name, binds)
|
955
|
-
end
|
956
|
-
|
957
714
|
# Returns the list of a table's column names, data types, and default values.
|
958
715
|
#
|
959
716
|
# The underlying query is roughly:
|
@@ -972,7 +729,7 @@ module ActiveRecord
|
|
972
729
|
# Query implementation notes:
|
973
730
|
# - format_type includes the column size constraint, e.g. varchar(50)
|
974
731
|
# - ::regclass is a function that gives the id for a table name
|
975
|
-
def column_definitions(table_name)
|
732
|
+
def column_definitions(table_name) # :nodoc:
|
976
733
|
exec_query(<<-end_sql, 'SCHEMA').rows
|
977
734
|
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
978
735
|
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
|
@@ -984,23 +741,13 @@ module ActiveRecord
|
|
984
741
|
end_sql
|
985
742
|
end
|
986
743
|
|
987
|
-
def
|
988
|
-
match_data = name.start_with?('"') ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/)
|
989
|
-
|
990
|
-
if match_data
|
991
|
-
rest = name[match_data[0].length, name.length]
|
992
|
-
rest = rest[1, rest.length] if rest.start_with? "."
|
993
|
-
[match_data[1], (rest.length > 0 ? rest : nil)]
|
994
|
-
end
|
995
|
-
end
|
996
|
-
|
997
|
-
def extract_table_ref_from_insert_sql(sql)
|
744
|
+
def extract_table_ref_from_insert_sql(sql) # :nodoc:
|
998
745
|
sql[/into\s+([^\(]*).*values\s*\(/im]
|
999
746
|
$1.strip if $1
|
1000
747
|
end
|
1001
748
|
|
1002
|
-
def create_table_definition(name, temporary, options, as = nil)
|
1003
|
-
TableDefinition.new native_database_types, name, temporary, options, as
|
749
|
+
def create_table_definition(name, temporary, options, as = nil) # :nodoc:
|
750
|
+
PostgreSQL::TableDefinition.new native_database_types, name, temporary, options, as
|
1004
751
|
end
|
1005
752
|
end
|
1006
753
|
end
|