activerecord 4.1.0 → 4.2.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 +776 -1330
- data/README.rdoc +15 -10
- data/lib/active_record/aggregations.rb +12 -8
- data/lib/active_record/association_relation.rb +4 -0
- data/lib/active_record/associations/alias_tracker.rb +14 -13
- data/lib/active_record/associations/association.rb +2 -2
- data/lib/active_record/associations/association_scope.rb +83 -43
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/builder/association.rb +15 -4
- data/lib/active_record/associations/builder/belongs_to.rb +7 -29
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +9 -6
- 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 +66 -29
- data/lib/active_record/associations/collection_proxy.rb +22 -26
- data/lib/active_record/associations/has_many_association.rb +65 -18
- data/lib/active_record/associations/has_many_through_association.rb +55 -27
- data/lib/active_record/associations/has_one_association.rb +0 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +19 -15
- data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
- data/lib/active_record/associations/join_dependency.rb +20 -12
- data/lib/active_record/associations/preloader/association.rb +34 -11
- data/lib/active_record/associations/preloader/through_association.rb +4 -3
- data/lib/active_record/associations/preloader.rb +49 -59
- data/lib/active_record/associations/singular_association.rb +25 -4
- data/lib/active_record/associations/through_association.rb +23 -14
- data/lib/active_record/associations.rb +171 -42
- data/lib/active_record/attribute.rb +149 -0
- data/lib/active_record/attribute_assignment.rb +18 -10
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -2
- data/lib/active_record/attribute_methods/dirty.rb +98 -44
- data/lib/active_record/attribute_methods/primary_key.rb +14 -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 +37 -147
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +34 -28
- data/lib/active_record/attribute_methods/write.rb +14 -21
- data/lib/active_record/attribute_methods.rb +67 -94
- data/lib/active_record/attribute_set/builder.rb +86 -0
- data/lib/active_record/attribute_set.rb +77 -0
- data/lib/active_record/attributes.rb +139 -0
- data/lib/active_record/autosave_association.rb +45 -38
- data/lib/active_record/base.rb +10 -20
- data/lib/active_record/callbacks.rb +7 -7
- data/lib/active_record/coders/json.rb +13 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +78 -52
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +38 -59
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +59 -55
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +126 -54
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +198 -64
- data/lib/active_record/connection_adapters/abstract/transaction.rb +126 -114
- data/lib/active_record/connection_adapters/abstract_adapter.rb +154 -55
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +240 -135
- data/lib/active_record/connection_adapters/column.rb +28 -239
- data/lib/active_record/connection_adapters/connection_specification.rb +16 -25
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +20 -22
- data/lib/active_record/connection_adapters/mysql_adapter.rb +65 -149
- 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 +39 -27
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +99 -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 +14 -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 +27 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -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 +15 -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 +97 -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 -374
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +55 -135
- 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 +127 -38
- data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +220 -466
- data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +66 -61
- data/lib/active_record/connection_handling.rb +3 -3
- data/lib/active_record/core.rb +143 -32
- data/lib/active_record/counter_cache.rb +60 -7
- data/lib/active_record/enum.rb +10 -11
- data/lib/active_record/errors.rb +49 -27
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixtures.rb +56 -70
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +35 -10
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/locking/optimistic.rb +35 -17
- data/lib/active_record/log_subscriber.rb +1 -1
- 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 +52 -49
- data/lib/active_record/model_schema.rb +49 -57
- data/lib/active_record/nested_attributes.rb +7 -7
- data/lib/active_record/null_relation.rb +19 -5
- data/lib/active_record/persistence.rb +50 -31
- data/lib/active_record/query_cache.rb +3 -3
- data/lib/active_record/querying.rb +10 -7
- data/lib/active_record/railtie.rb +14 -11
- data/lib/active_record/railties/databases.rake +56 -54
- data/lib/active_record/readonly_attributes.rb +0 -1
- data/lib/active_record/reflection.rb +286 -102
- data/lib/active_record/relation/batches.rb +0 -1
- data/lib/active_record/relation/calculations.rb +39 -31
- data/lib/active_record/relation/delegation.rb +2 -2
- data/lib/active_record/relation/finder_methods.rb +80 -36
- data/lib/active_record/relation/merger.rb +25 -30
- data/lib/active_record/relation/predicate_builder/array_handler.rb +31 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +11 -10
- data/lib/active_record/relation/query_methods.rb +141 -55
- data/lib/active_record/relation/spawn_methods.rb +3 -0
- data/lib/active_record/relation.rb +69 -30
- 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 +58 -26
- data/lib/active_record/schema_migration.rb +11 -0
- data/lib/active_record/scoping/default.rb +8 -7
- 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 +19 -10
- data/lib/active_record/tasks/database_tasks.rb +73 -7
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +11 -9
- data/lib/active_record/transactions.rb +37 -21
- 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 +30 -0
- data/lib/active_record/type/date.rb +46 -0
- data/lib/active_record/type/date_time.rb +43 -0
- data/lib/active_record/type/decimal.rb +40 -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 +17 -0
- data/lib/active_record/type/integer.rb +55 -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 +56 -0
- data/lib/active_record/type/string.rb +36 -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 +101 -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 +6 -4
- data/lib/active_record/validations/uniqueness.rb +11 -17
- data/lib/active_record/validations.rb +25 -19
- data/lib/active_record.rb +3 -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 +4 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb +6 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
- metadata +65 -10
- 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:
|
@@ -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
|
@@ -637,10 +316,6 @@ module ActiveRecord
|
|
637
316
|
self.client_min_messages = old
|
638
317
|
end
|
639
318
|
|
640
|
-
def supports_insert_with_returning?
|
641
|
-
true
|
642
|
-
end
|
643
|
-
|
644
319
|
def supports_ddl_transactions?
|
645
320
|
true
|
646
321
|
end
|
@@ -659,6 +334,10 @@ module ActiveRecord
|
|
659
334
|
postgresql_version >= 90200
|
660
335
|
end
|
661
336
|
|
337
|
+
def supports_materialized_views?
|
338
|
+
postgresql_version >= 90300
|
339
|
+
end
|
340
|
+
|
662
341
|
def enable_extension(name)
|
663
342
|
exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
|
664
343
|
reload_type_map
|
@@ -675,14 +354,13 @@ module ActiveRecord
|
|
675
354
|
if supports_extensions?
|
676
355
|
res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled",
|
677
356
|
'SCHEMA'
|
678
|
-
res.
|
357
|
+
res.cast_values.first
|
679
358
|
end
|
680
359
|
end
|
681
360
|
|
682
361
|
def extensions
|
683
362
|
if supports_extensions?
|
684
|
-
|
685
|
-
res.rows.map { |r| res.column_types['extname'].type_cast r.first }
|
363
|
+
exec_query("SELECT extname from pg_extension", "SCHEMA").cast_values
|
686
364
|
else
|
687
365
|
super
|
688
366
|
end
|
@@ -699,25 +377,6 @@ module ActiveRecord
|
|
699
377
|
exec_query "SET SESSION AUTHORIZATION #{user}"
|
700
378
|
end
|
701
379
|
|
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
380
|
def use_insert_returning?
|
722
381
|
@use_insert_returning
|
723
382
|
end
|
@@ -727,9 +386,24 @@ module ActiveRecord
|
|
727
386
|
end
|
728
387
|
|
729
388
|
def update_table_definition(table_name, base) #:nodoc:
|
730
|
-
Table.new(table_name, base)
|
389
|
+
PostgreSQL::Table.new(table_name, base)
|
390
|
+
end
|
391
|
+
|
392
|
+
def lookup_cast_type(sql_type) # :nodoc:
|
393
|
+
oid = execute("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").first['oid'].to_i
|
394
|
+
super(oid)
|
395
|
+
end
|
396
|
+
|
397
|
+
def column_name_for_operation(operation, node) # :nodoc:
|
398
|
+
OPERATION_ALIASES.fetch(operation) { operation.downcase }
|
731
399
|
end
|
732
400
|
|
401
|
+
OPERATION_ALIASES = { # :nodoc:
|
402
|
+
"maximum" => "max",
|
403
|
+
"minimum" => "min",
|
404
|
+
"average" => "avg",
|
405
|
+
}
|
406
|
+
|
733
407
|
protected
|
734
408
|
|
735
409
|
# Returns the version of the connected PostgreSQL server.
|
@@ -756,63 +430,166 @@ module ActiveRecord
|
|
756
430
|
|
757
431
|
private
|
758
432
|
|
759
|
-
def
|
760
|
-
|
761
|
-
|
433
|
+
def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
|
434
|
+
if !type_map.key?(oid)
|
435
|
+
load_additional_types(type_map, [oid])
|
436
|
+
end
|
762
437
|
|
763
|
-
|
764
|
-
|
765
|
-
|
438
|
+
type_map.fetch(oid, fmod, sql_type) {
|
439
|
+
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
|
440
|
+
Type::Value.new.tap do |cast_type|
|
441
|
+
type_map.register_type(oid, cast_type)
|
442
|
+
end
|
443
|
+
}
|
766
444
|
end
|
767
445
|
|
768
|
-
def
|
769
|
-
|
446
|
+
def initialize_type_map(m) # :nodoc:
|
447
|
+
register_class_with_limit m, 'int2', OID::Integer
|
448
|
+
m.alias_type 'int4', 'int2'
|
449
|
+
m.alias_type 'int8', 'int2'
|
450
|
+
m.alias_type 'oid', 'int2'
|
451
|
+
m.register_type 'float4', OID::Float.new
|
452
|
+
m.alias_type 'float8', 'float4'
|
453
|
+
m.register_type 'text', Type::Text.new
|
454
|
+
register_class_with_limit m, 'varchar', Type::String
|
455
|
+
m.alias_type 'char', 'varchar'
|
456
|
+
m.alias_type 'name', 'varchar'
|
457
|
+
m.alias_type 'bpchar', 'varchar'
|
458
|
+
m.register_type 'bool', Type::Boolean.new
|
459
|
+
register_class_with_limit m, 'bit', OID::Bit
|
460
|
+
register_class_with_limit m, 'varbit', OID::BitVarying
|
461
|
+
m.alias_type 'timestamptz', 'timestamp'
|
462
|
+
m.register_type 'date', OID::Date.new
|
463
|
+
m.register_type 'time', OID::Time.new
|
464
|
+
|
465
|
+
m.register_type 'money', OID::Money.new
|
466
|
+
m.register_type 'bytea', OID::Bytea.new
|
467
|
+
m.register_type 'point', OID::Point.new
|
468
|
+
m.register_type 'hstore', OID::Hstore.new
|
469
|
+
m.register_type 'json', OID::Json.new
|
470
|
+
m.register_type 'jsonb', OID::Jsonb.new
|
471
|
+
m.register_type 'cidr', OID::Cidr.new
|
472
|
+
m.register_type 'inet', OID::Inet.new
|
473
|
+
m.register_type 'uuid', OID::Uuid.new
|
474
|
+
m.register_type 'xml', OID::Xml.new
|
475
|
+
m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
|
476
|
+
m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
|
477
|
+
m.register_type 'citext', OID::SpecializedString.new(:citext)
|
478
|
+
m.register_type 'ltree', OID::SpecializedString.new(:ltree)
|
479
|
+
|
480
|
+
# FIXME: why are we keeping these types as strings?
|
481
|
+
m.alias_type 'interval', 'varchar'
|
482
|
+
m.alias_type 'path', 'varchar'
|
483
|
+
m.alias_type 'line', 'varchar'
|
484
|
+
m.alias_type 'polygon', 'varchar'
|
485
|
+
m.alias_type 'circle', 'varchar'
|
486
|
+
m.alias_type 'lseg', 'varchar'
|
487
|
+
m.alias_type 'box', 'varchar'
|
488
|
+
|
489
|
+
m.register_type 'timestamp' do |_, _, sql_type|
|
490
|
+
precision = extract_precision(sql_type)
|
491
|
+
OID::DateTime.new(precision: precision)
|
492
|
+
end
|
770
493
|
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
#
|
776
|
-
|
777
|
-
|
494
|
+
m.register_type 'numeric' do |_, fmod, sql_type|
|
495
|
+
precision = extract_precision(sql_type)
|
496
|
+
scale = extract_scale(sql_type)
|
497
|
+
|
498
|
+
# The type for the numeric depends on the width of the field,
|
499
|
+
# so we'll do something special here.
|
500
|
+
#
|
501
|
+
# When dealing with decimal columns:
|
502
|
+
#
|
503
|
+
# places after decimal = fmod - 4 & 0xffff
|
504
|
+
# places before decimal = (fmod - 4) >> 16 & 0xffff
|
505
|
+
if fmod && (fmod - 4 & 0xffff).zero?
|
506
|
+
# FIXME: Remove this class, and the second argument to
|
507
|
+
# lookups on PG
|
508
|
+
Type::DecimalWithoutScale.new(precision: precision)
|
509
|
+
else
|
510
|
+
OID::Decimal.new(precision: precision, scale: scale)
|
778
511
|
end
|
779
|
-
|
780
|
-
vector = OID::Vector.new row['typdelim'], type_map[row['typelem'].to_i]
|
781
512
|
end
|
782
513
|
|
783
|
-
|
784
|
-
type_map
|
514
|
+
load_additional_types(m)
|
785
515
|
end
|
786
516
|
|
787
|
-
def
|
788
|
-
|
789
|
-
|
517
|
+
def extract_limit(sql_type) # :nodoc:
|
518
|
+
case sql_type
|
519
|
+
when /^bigint/i, /^int8/i
|
520
|
+
8
|
521
|
+
when /^smallint/i
|
522
|
+
2
|
523
|
+
else
|
524
|
+
super
|
525
|
+
end
|
526
|
+
end
|
790
527
|
|
791
|
-
|
792
|
-
|
793
|
-
|
528
|
+
# Extracts the value from a PostgreSQL column default definition.
|
529
|
+
def extract_value_from_default(oid, default) # :nodoc:
|
530
|
+
case default
|
531
|
+
# Quoted types
|
532
|
+
when /\A[\(B]?'(.*)'::/m
|
533
|
+
$1.gsub(/''/, "'")
|
534
|
+
# Boolean types
|
535
|
+
when 'true', 'false'
|
536
|
+
default
|
537
|
+
# Numeric types
|
538
|
+
when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
|
539
|
+
$1
|
540
|
+
# Object identifier types
|
541
|
+
when /\A-?\d+\z/
|
542
|
+
$1
|
543
|
+
else
|
544
|
+
# Anything else is blank, some user type, or some function
|
545
|
+
# and we can't know the value of that, so return nil.
|
546
|
+
nil
|
794
547
|
end
|
548
|
+
end
|
795
549
|
|
796
|
-
|
550
|
+
def extract_default_function(default_value, default) # :nodoc:
|
551
|
+
default if has_default_function?(default_value, default)
|
552
|
+
end
|
797
553
|
|
798
|
-
|
554
|
+
def has_default_function?(default_value, default) # :nodoc:
|
555
|
+
!default_value && (%r{\w+\(.*\)} === default)
|
556
|
+
end
|
799
557
|
|
800
|
-
|
801
|
-
|
802
|
-
|
558
|
+
def load_additional_types(type_map, oids = nil) # :nodoc:
|
559
|
+
if supports_ranges?
|
560
|
+
query = <<-SQL
|
561
|
+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
|
562
|
+
FROM pg_type as t
|
563
|
+
LEFT JOIN pg_range as r ON oid = rngtypid
|
564
|
+
SQL
|
565
|
+
else
|
566
|
+
query = <<-SQL
|
567
|
+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
|
568
|
+
FROM pg_type as t
|
569
|
+
SQL
|
803
570
|
end
|
804
571
|
|
805
|
-
|
806
|
-
|
807
|
-
array = OID::Array.new type_map[row['typelem'].to_i]
|
808
|
-
type_map[row['oid'].to_i] = array
|
572
|
+
if oids
|
573
|
+
query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
|
809
574
|
end
|
575
|
+
|
576
|
+
initializer = OID::TypeMapInitializer.new(type_map)
|
577
|
+
records = execute(query, 'SCHEMA')
|
578
|
+
initializer.run(records)
|
810
579
|
end
|
811
580
|
|
812
581
|
FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
|
813
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
|
+
|
814
591
|
def exec_no_cache(sql, name, binds)
|
815
|
-
log(sql, name, binds) { @connection.async_exec(sql) }
|
592
|
+
log(sql, name, binds) { @connection.async_exec(sql, []) }
|
816
593
|
end
|
817
594
|
|
818
595
|
def exec_cache(sql, name, binds)
|
@@ -822,9 +599,7 @@ module ActiveRecord
|
|
822
599
|
}
|
823
600
|
|
824
601
|
log(sql, name, type_casted_binds, stmt_key) do
|
825
|
-
@connection.
|
826
|
-
@connection.block
|
827
|
-
@connection.get_last_result
|
602
|
+
@connection.exec_prepared(stmt_key, type_casted_binds.map { |_, val| val })
|
828
603
|
end
|
829
604
|
rescue ActiveRecord::StatementInvalid => e
|
830
605
|
pgerror = e.original_exception
|
@@ -870,11 +645,6 @@ module ActiveRecord
|
|
870
645
|
@statements[sql_key]
|
871
646
|
end
|
872
647
|
|
873
|
-
# The internal PostgreSQL identifier of the money data type.
|
874
|
-
MONEY_COLUMN_TYPE_OID = 790 #:nodoc:
|
875
|
-
# The internal PostgreSQL identifier of the BYTEA data type.
|
876
|
-
BYTEA_COLUMN_TYPE_OID = 17 #:nodoc:
|
877
|
-
|
878
648
|
# Connects to a PostgreSQL server and sets up the adapter depending on the
|
879
649
|
# connected server's characteristics.
|
880
650
|
def connect
|
@@ -883,14 +653,14 @@ module ActiveRecord
|
|
883
653
|
# Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of
|
884
654
|
# PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision
|
885
655
|
# should know about this but can't detect it there, so deal with it here.
|
886
|
-
|
656
|
+
OID::Money.precision = (postgresql_version >= 80300) ? 19 : 10
|
887
657
|
|
888
658
|
configure_connection
|
889
659
|
rescue ::PG::Error => error
|
890
660
|
if error.message.include?("does not exist")
|
891
|
-
raise ActiveRecord::NoDatabaseError.new(error.message)
|
661
|
+
raise ActiveRecord::NoDatabaseError.new(error.message, error)
|
892
662
|
else
|
893
|
-
raise
|
663
|
+
raise
|
894
664
|
end
|
895
665
|
end
|
896
666
|
|
@@ -921,9 +691,9 @@ module ActiveRecord
|
|
921
691
|
variables.map do |k, v|
|
922
692
|
if v == ':default' || v == :default
|
923
693
|
# Sets the value to the global or compile default
|
924
|
-
execute("SET SESSION #{k
|
694
|
+
execute("SET SESSION #{k} TO DEFAULT", 'SCHEMA')
|
925
695
|
elsif !v.nil?
|
926
|
-
execute("SET SESSION #{k
|
696
|
+
execute("SET SESSION #{k} TO #{quote(v)}", 'SCHEMA')
|
927
697
|
end
|
928
698
|
end
|
929
699
|
end
|
@@ -941,12 +711,6 @@ module ActiveRecord
|
|
941
711
|
exec_query("SELECT currval('#{sequence_name}')", 'SQL')
|
942
712
|
end
|
943
713
|
|
944
|
-
# Executes a SELECT query and returns the results, performing any data type
|
945
|
-
# conversions that are required to be performed here instead of in PostgreSQLColumn.
|
946
|
-
def select(sql, name = nil, binds = [])
|
947
|
-
exec_query(sql, name, binds)
|
948
|
-
end
|
949
|
-
|
950
714
|
# Returns the list of a table's column names, data types, and default values.
|
951
715
|
#
|
952
716
|
# The underlying query is roughly:
|
@@ -965,7 +729,7 @@ module ActiveRecord
|
|
965
729
|
# Query implementation notes:
|
966
730
|
# - format_type includes the column size constraint, e.g. varchar(50)
|
967
731
|
# - ::regclass is a function that gives the id for a table name
|
968
|
-
def column_definitions(table_name)
|
732
|
+
def column_definitions(table_name) # :nodoc:
|
969
733
|
exec_query(<<-end_sql, 'SCHEMA').rows
|
970
734
|
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
971
735
|
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
|
@@ -977,23 +741,13 @@ module ActiveRecord
|
|
977
741
|
end_sql
|
978
742
|
end
|
979
743
|
|
980
|
-
def
|
981
|
-
match_data = name.start_with?('"') ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/)
|
982
|
-
|
983
|
-
if match_data
|
984
|
-
rest = name[match_data[0].length, name.length]
|
985
|
-
rest = rest[1, rest.length] if rest.start_with? "."
|
986
|
-
[match_data[1], (rest.length > 0 ? rest : nil)]
|
987
|
-
end
|
988
|
-
end
|
989
|
-
|
990
|
-
def extract_table_ref_from_insert_sql(sql)
|
744
|
+
def extract_table_ref_from_insert_sql(sql) # :nodoc:
|
991
745
|
sql[/into\s+([^\(]*).*values\s*\(/im]
|
992
746
|
$1.strip if $1
|
993
747
|
end
|
994
748
|
|
995
|
-
def create_table_definition(name, temporary, options, as = nil)
|
996
|
-
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
|
997
751
|
end
|
998
752
|
end
|
999
753
|
end
|