activerecord 4.0.0.beta1 → 4.0.0.rc1
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 +573 -30
- data/README.rdoc +3 -3
- data/lib/active_record.rb +8 -2
- data/lib/active_record/associations.rb +16 -9
- data/lib/active_record/associations/association.rb +8 -6
- data/lib/active_record/associations/association_scope.rb +2 -1
- data/lib/active_record/associations/belongs_to_association.rb +2 -2
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/belongs_to.rb +37 -5
- data/lib/active_record/associations/collection_association.rb +38 -14
- data/lib/active_record/associations/collection_proxy.rb +18 -15
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +3 -3
- data/lib/active_record/associations/has_many_association.rb +4 -3
- data/lib/active_record/associations/has_many_through_association.rb +1 -1
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +29 -8
- data/lib/active_record/associations/join_dependency/join_association.rb +26 -6
- data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_part.rb +6 -6
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
- data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +5 -5
- data/lib/active_record/attribute_methods.rb +20 -5
- data/lib/active_record/attribute_methods/dirty.rb +5 -1
- data/lib/active_record/attribute_methods/primary_key.rb +1 -1
- data/lib/active_record/attribute_methods/serialization.rb +9 -2
- data/lib/active_record/autosave_association.rb +19 -5
- data/lib/active_record/base.rb +3 -3
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +8 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +3 -9
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +2 -8
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +60 -61
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +13 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +291 -153
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -1
- data/lib/active_record/connection_adapters/abstract_adapter.rb +92 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +55 -29
- data/lib/active_record/connection_adapters/column.rb +4 -4
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -2
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -3
- data/lib/active_record/connection_adapters/mysql_adapter.rb +5 -5
- data/lib/active_record/connection_adapters/postgresql/cast.rb +22 -2
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +50 -9
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +53 -24
- data/lib/active_record/connection_adapters/schema_cache.rb +35 -7
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +13 -5
- data/lib/active_record/connection_handling.rb +7 -7
- data/lib/active_record/core.rb +43 -8
- data/lib/active_record/counter_cache.rb +2 -1
- data/lib/active_record/errors.rb +11 -10
- data/lib/active_record/explain.rb +9 -7
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +3 -2
- data/lib/active_record/fixture_set/file.rb +1 -2
- data/lib/active_record/fixtures.rb +13 -7
- data/lib/active_record/inheritance.rb +12 -4
- data/lib/active_record/integration.rb +3 -3
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/log_subscriber.rb +2 -2
- data/lib/active_record/migration.rb +69 -21
- data/lib/active_record/model_schema.rb +1 -1
- data/lib/active_record/nested_attributes.rb +98 -46
- data/lib/active_record/persistence.rb +3 -3
- data/lib/active_record/querying.rb +1 -1
- data/lib/active_record/railtie.rb +18 -4
- data/lib/active_record/railties/console_sandbox.rb +3 -2
- data/lib/active_record/railties/controller_runtime.rb +2 -1
- data/lib/active_record/railties/databases.rake +38 -80
- data/lib/active_record/reflection.rb +36 -3
- data/lib/active_record/relation.rb +18 -8
- data/lib/active_record/relation/calculations.rb +10 -5
- data/lib/active_record/relation/delegation.rb +3 -5
- data/lib/active_record/relation/finder_methods.rb +27 -14
- data/lib/active_record/relation/merger.rb +30 -2
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_methods.rb +113 -16
- data/lib/active_record/runtime_registry.rb +17 -0
- data/lib/active_record/schema_dumper.rb +5 -1
- data/lib/active_record/schema_migration.rb +8 -5
- data/lib/active_record/scoping.rb +56 -2
- data/lib/active_record/scoping/default.rb +12 -11
- data/lib/active_record/scoping/named.rb +7 -3
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/statement_cache.rb +26 -0
- data/lib/active_record/tasks/database_tasks.rb +55 -10
- data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -2
- data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
- data/lib/active_record/timestamp.rb +6 -0
- data/lib/active_record/transactions.rb +7 -3
- data/lib/active_record/validations.rb +1 -2
- data/lib/active_record/validations/uniqueness.rb +7 -3
- data/lib/active_record/version.rb +7 -6
- data/lib/rails/generators/active_record/migration/migration_generator.rb +9 -2
- data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb +4 -1
- metadata +17 -12
- data/examples/associations.png +0 -0
@@ -2,6 +2,17 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters
|
3
3
|
class PostgreSQLColumn < Column
|
4
4
|
module Cast
|
5
|
+
def point_to_string(point)
|
6
|
+
"(#{point[0]},#{point[1]})"
|
7
|
+
end
|
8
|
+
|
9
|
+
def string_to_point(string)
|
10
|
+
if string[0] == '(' && string[-1] == ')'
|
11
|
+
string = string[1...-1]
|
12
|
+
end
|
13
|
+
string.split(',').map{ |v| Float(v) }
|
14
|
+
end
|
15
|
+
|
5
16
|
def string_to_time(string)
|
6
17
|
return string unless String === string
|
7
18
|
|
@@ -15,6 +26,15 @@ module ActiveRecord
|
|
15
26
|
end
|
16
27
|
end
|
17
28
|
|
29
|
+
def string_to_bit(value)
|
30
|
+
case value
|
31
|
+
when /^0x/i
|
32
|
+
value[2..-1].hex.to_s(2) # Hexadecimal notation
|
33
|
+
else
|
34
|
+
value # Bit-string notation
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
18
38
|
def hstore_to_string(object)
|
19
39
|
if Hash === object
|
20
40
|
object.map { |k,v|
|
@@ -30,8 +50,8 @@ module ActiveRecord
|
|
30
50
|
nil
|
31
51
|
elsif String === string
|
32
52
|
Hash[string.scan(HstorePair).map { |k,v|
|
33
|
-
v = v.upcase == 'NULL' ? nil : v.gsub(
|
34
|
-
k = k.gsub(
|
53
|
+
v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
54
|
+
k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
35
55
|
[k,v]
|
36
56
|
}]
|
37
57
|
else
|
@@ -18,8 +18,19 @@ module ActiveRecord
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
class Bit < Type
|
22
|
+
def type_cast(value)
|
23
|
+
if String === value
|
24
|
+
ConnectionAdapters::PostgreSQLColumn.string_to_bit value
|
25
|
+
else
|
26
|
+
value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
21
31
|
class Bytea < Type
|
22
32
|
def type_cast(value)
|
33
|
+
return if value.nil?
|
23
34
|
PGconn.unescape_bytea value
|
24
35
|
end
|
25
36
|
end
|
@@ -63,6 +74,16 @@ module ActiveRecord
|
|
63
74
|
end
|
64
75
|
end
|
65
76
|
|
77
|
+
class Point < Type
|
78
|
+
def type_cast(value)
|
79
|
+
if String === value
|
80
|
+
ConnectionAdapters::PostgreSQLColumn.string_to_point value
|
81
|
+
else
|
82
|
+
value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
66
87
|
class Array < Type
|
67
88
|
attr_reader :subtype
|
68
89
|
def initialize(subtype)
|
@@ -312,27 +333,25 @@ module ActiveRecord
|
|
312
333
|
# FIXME: why are we keeping these types as strings?
|
313
334
|
alias_type 'tsvector', 'text'
|
314
335
|
alias_type 'interval', 'text'
|
315
|
-
alias_type 'bit', 'text'
|
316
|
-
alias_type 'varbit', 'text'
|
317
336
|
alias_type 'macaddr', 'text'
|
318
337
|
alias_type 'uuid', 'text'
|
319
338
|
|
320
|
-
# FIXME: I don't think this is correct. We should probably be returning a parsed date,
|
321
|
-
# but the tests pass with a string returned.
|
322
|
-
register_type 'timestamptz', OID::Identity.new
|
323
|
-
|
324
339
|
register_type 'money', OID::Money.new
|
325
340
|
register_type 'bytea', OID::Bytea.new
|
326
341
|
register_type 'bool', OID::Boolean.new
|
342
|
+
register_type 'bit', OID::Bit.new
|
343
|
+
register_type 'varbit', OID::Bit.new
|
327
344
|
|
328
345
|
register_type 'float4', OID::Float.new
|
329
346
|
alias_type 'float8', 'float4'
|
330
347
|
|
331
348
|
register_type 'timestamp', OID::Timestamp.new
|
349
|
+
register_type 'timestamptz', OID::Timestamp.new
|
332
350
|
register_type 'date', OID::Date.new
|
333
351
|
register_type 'time', OID::Time.new
|
334
352
|
|
335
353
|
register_type 'path', OID::Identity.new
|
354
|
+
register_type 'point', OID::Point.new
|
336
355
|
register_type 'polygon', OID::Identity.new
|
337
356
|
register_type 'circle', OID::Identity.new
|
338
357
|
register_type 'hstore', OID::Hstore.new
|
@@ -18,27 +18,33 @@ module ActiveRecord
|
|
18
18
|
def quote(value, column = nil) #:nodoc:
|
19
19
|
return super unless column
|
20
20
|
|
21
|
+
sql_type = type_to_sql(column.type, column.limit, column.precision, column.scale)
|
22
|
+
|
21
23
|
case value
|
22
24
|
when Range
|
23
|
-
if /range$/ =~
|
24
|
-
"'#{PostgreSQLColumn.range_to_string(value)}'::#{
|
25
|
+
if /range$/ =~ sql_type
|
26
|
+
"'#{PostgreSQLColumn.range_to_string(value)}'::#{sql_type}"
|
25
27
|
else
|
26
28
|
super
|
27
29
|
end
|
28
30
|
when Array
|
29
|
-
|
30
|
-
|
31
|
+
case sql_type
|
32
|
+
when 'point' then super(PostgreSQLColumn.point_to_string(value))
|
31
33
|
else
|
32
|
-
|
34
|
+
if column.array
|
35
|
+
"'#{PostgreSQLColumn.array_to_string(value, column, self).gsub(/'/, "''")}'"
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
33
39
|
end
|
34
40
|
when Hash
|
35
|
-
case
|
41
|
+
case sql_type
|
36
42
|
when 'hstore' then super(PostgreSQLColumn.hstore_to_string(value), column)
|
37
43
|
when 'json' then super(PostgreSQLColumn.json_to_string(value), column)
|
38
44
|
else super
|
39
45
|
end
|
40
46
|
when IPAddr
|
41
|
-
case
|
47
|
+
case sql_type
|
42
48
|
when 'inet', 'cidr' then super(PostgreSQLColumn.cidr_to_string(value), column)
|
43
49
|
else super
|
44
50
|
end
|
@@ -51,11 +57,14 @@ module ActiveRecord
|
|
51
57
|
super
|
52
58
|
end
|
53
59
|
when Numeric
|
54
|
-
|
55
|
-
|
56
|
-
|
60
|
+
if sql_type == 'money' || [:string, :text].include?(column.type)
|
61
|
+
# Not truly string input, so doesn't require (or allow) escape string syntax.
|
62
|
+
"'#{value}'"
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
57
66
|
when String
|
58
|
-
case
|
67
|
+
case sql_type
|
59
68
|
when 'bytea' then "'#{escape_bytea(value)}'"
|
60
69
|
when 'xml' then "xml '#{quote_string(value)}'"
|
61
70
|
when /^bit/
|
@@ -87,8 +96,12 @@ module ActiveRecord
|
|
87
96
|
super(value, column)
|
88
97
|
end
|
89
98
|
when Array
|
90
|
-
|
91
|
-
PostgreSQLColumn.
|
99
|
+
case column.sql_type
|
100
|
+
when 'point' then PostgreSQLColumn.point_to_string(value)
|
101
|
+
else
|
102
|
+
return super(value, column) unless column.array
|
103
|
+
PostgreSQLColumn.array_to_string(value, column, self)
|
104
|
+
end
|
92
105
|
when String
|
93
106
|
return super(value, column) unless 'bytea' == column.sql_type
|
94
107
|
{ :value => value, :format => 1 }
|
@@ -1,6 +1,42 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
class PostgreSQLAdapter < AbstractAdapter
|
4
|
+
class SchemaCreation < AbstractAdapter::SchemaCreation
|
5
|
+
private
|
6
|
+
|
7
|
+
def visit_AddColumn(o)
|
8
|
+
sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
|
9
|
+
sql = "ADD COLUMN #{quote_column_name(o.name)} #{sql_type}"
|
10
|
+
add_column_options!(sql, column_options(o))
|
11
|
+
end
|
12
|
+
|
13
|
+
def visit_ColumnDefinition(o)
|
14
|
+
sql = super
|
15
|
+
if o.primary_key? && o.type == :uuid
|
16
|
+
sql << " PRIMARY KEY "
|
17
|
+
add_column_options!(sql, column_options(o))
|
18
|
+
end
|
19
|
+
sql
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_column_options!(sql, options)
|
23
|
+
if options[:array] || options[:column].try(:array)
|
24
|
+
sql << '[]'
|
25
|
+
end
|
26
|
+
|
27
|
+
column = options.fetch(:column) { return super }
|
28
|
+
if column.type == :uuid && options[:default] =~ /\(\)/
|
29
|
+
sql << " DEFAULT #{options[:default]}"
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def schema_creation
|
37
|
+
SchemaCreation.new self
|
38
|
+
end
|
39
|
+
|
4
40
|
module SchemaStatements
|
5
41
|
# Drops the database specified on the +name+ attribute
|
6
42
|
# and creates it again using the provided +options+.
|
@@ -120,12 +156,15 @@ module ActiveRecord
|
|
120
156
|
|
121
157
|
column_names = columns.values_at(*indkey).compact
|
122
158
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
159
|
+
unless column_names.empty?
|
160
|
+
# add info on sort order for columns (only desc order is explicitly specified, asc is the default)
|
161
|
+
desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
|
162
|
+
orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
|
163
|
+
where = inddef.scan(/WHERE (.+)$/).flatten[0]
|
164
|
+
using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
|
127
165
|
|
128
|
-
|
166
|
+
IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using)
|
167
|
+
end
|
129
168
|
end.compact
|
130
169
|
end
|
131
170
|
|
@@ -337,10 +376,7 @@ module ActiveRecord
|
|
337
376
|
# See TableDefinition#column for details of the options you can use.
|
338
377
|
def add_column(table_name, column_name, type, options = {})
|
339
378
|
clear_cache!
|
340
|
-
|
341
|
-
add_column_options!(add_column_sql, options)
|
342
|
-
|
343
|
-
execute add_column_sql
|
379
|
+
super
|
344
380
|
end
|
345
381
|
|
346
382
|
# Changes the column of a table.
|
@@ -375,6 +411,11 @@ module ActiveRecord
|
|
375
411
|
rename_column_indexes(table_name, column_name, new_column_name)
|
376
412
|
end
|
377
413
|
|
414
|
+
def add_index(table_name, column_name, options = {}) #:nodoc:
|
415
|
+
index_name, index_type, index_columns, index_options, index_algorithm, index_using = add_index_options(table_name, column_name, options)
|
416
|
+
execute "CREATE #{index_type} INDEX #{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{index_using} (#{index_columns})#{index_options}"
|
417
|
+
end
|
418
|
+
|
378
419
|
def remove_index!(table_name, index_name) #:nodoc:
|
379
420
|
execute "DROP INDEX #{quote_table_name(index_name)}"
|
380
421
|
end
|
@@ -16,7 +16,7 @@ require 'pg'
|
|
16
16
|
require 'ipaddr'
|
17
17
|
|
18
18
|
module ActiveRecord
|
19
|
-
module ConnectionHandling
|
19
|
+
module ConnectionHandling # :nodoc:
|
20
20
|
VALID_CONN_PARAMS = [:host, :hostaddr, :port, :dbname, :user, :password, :connect_timeout,
|
21
21
|
:client_encoding, :options, :application_name, :fallback_application_name,
|
22
22
|
:keepalives, :keepalives_idle, :keepalives_interval, :keepalives_count,
|
@@ -24,7 +24,7 @@ module ActiveRecord
|
|
24
24
|
:requirepeer, :krbsrvname, :gsslib, :service]
|
25
25
|
|
26
26
|
# Establishes a connection to the database that's used by all Active Record objects
|
27
|
-
def postgresql_connection(config)
|
27
|
+
def postgresql_connection(config)
|
28
28
|
conn_params = config.symbolize_keys
|
29
29
|
|
30
30
|
conn_params.delete_if { |_, v| v.nil? }
|
@@ -80,7 +80,7 @@ module ActiveRecord
|
|
80
80
|
when /\A'(.*)'::(num|date|tstz|ts|int4|int8)range\z/m
|
81
81
|
$1
|
82
82
|
# Numeric types
|
83
|
-
when /\A\(?(-?\d+(\.\d*)?\)?)\z/
|
83
|
+
when /\A\(?(-?\d+(\.\d*)?\)?(::bigint)?)\z/
|
84
84
|
$1
|
85
85
|
# Character types
|
86
86
|
when /\A\(?'(.*)'::.*\b(?:character varying|bpchar|text)\z/m
|
@@ -263,7 +263,7 @@ module ActiveRecord
|
|
263
263
|
attr_accessor :array
|
264
264
|
end
|
265
265
|
|
266
|
-
|
266
|
+
module ColumnMethods
|
267
267
|
def xml(*args)
|
268
268
|
options = args.extract_options!
|
269
269
|
column(args[0], 'xml', options)
|
@@ -325,6 +325,17 @@ module ActiveRecord
|
|
325
325
|
def json(name, options = {})
|
326
326
|
column(name, 'json', options)
|
327
327
|
end
|
328
|
+
end
|
329
|
+
|
330
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
331
|
+
include ColumnMethods
|
332
|
+
|
333
|
+
def primary_key(name, type = :primary_key, options = {})
|
334
|
+
return super unless type == :uuid
|
335
|
+
options[:default] ||= 'uuid_generate_v4()'
|
336
|
+
options[:primary_key] = true
|
337
|
+
column name, type, options
|
338
|
+
end
|
328
339
|
|
329
340
|
def column(name, type = nil, options = {})
|
330
341
|
super
|
@@ -334,16 +345,21 @@ module ActiveRecord
|
|
334
345
|
self
|
335
346
|
end
|
336
347
|
|
348
|
+
def xml(options = {})
|
349
|
+
column(args[0], :text, options)
|
350
|
+
end
|
351
|
+
|
337
352
|
private
|
338
353
|
|
339
|
-
def
|
340
|
-
|
341
|
-
@columns << definition
|
342
|
-
@columns_hash[name] = definition
|
343
|
-
definition
|
354
|
+
def create_column_definition(name, type)
|
355
|
+
ColumnDefinition.new name, type
|
344
356
|
end
|
345
357
|
end
|
346
358
|
|
359
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
360
|
+
include ColumnMethods
|
361
|
+
end
|
362
|
+
|
347
363
|
ADAPTER_NAME = 'PostgreSQL'
|
348
364
|
|
349
365
|
NATIVE_DATABASE_TYPES = {
|
@@ -417,6 +433,10 @@ module ActiveRecord
|
|
417
433
|
true
|
418
434
|
end
|
419
435
|
|
436
|
+
def index_algorithms
|
437
|
+
{ concurrently: 'CONCURRENTLY' }
|
438
|
+
end
|
439
|
+
|
420
440
|
class StatementPool < ConnectionAdapters::StatementPool
|
421
441
|
def initialize(connection, max)
|
422
442
|
super
|
@@ -481,7 +501,7 @@ module ActiveRecord
|
|
481
501
|
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
482
502
|
@visitor = Arel::Visitors::PostgreSQL.new self
|
483
503
|
else
|
484
|
-
@visitor =
|
504
|
+
@visitor = unprepared_visitor
|
485
505
|
end
|
486
506
|
|
487
507
|
@connection_parameters, @config = connection_parameters, config
|
@@ -510,8 +530,7 @@ module ActiveRecord
|
|
510
530
|
|
511
531
|
# Is this connection alive and ready for queries?
|
512
532
|
def active?
|
513
|
-
@connection.
|
514
|
-
true
|
533
|
+
@connection.connect_poll != PG::PGRES_POLLING_FAILED
|
515
534
|
rescue PGError
|
516
535
|
false
|
517
536
|
end
|
@@ -586,13 +605,13 @@ module ActiveRecord
|
|
586
605
|
end
|
587
606
|
|
588
607
|
def enable_extension(name)
|
589
|
-
exec_query("CREATE EXTENSION IF NOT EXISTS #{name}").tap {
|
608
|
+
exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
|
590
609
|
reload_type_map
|
591
610
|
}
|
592
611
|
end
|
593
612
|
|
594
613
|
def disable_extension(name)
|
595
|
-
exec_query("DROP EXTENSION IF EXISTS #{name} CASCADE").tap {
|
614
|
+
exec_query("DROP EXTENSION IF EXISTS \"#{name}\" CASCADE").tap {
|
596
615
|
reload_type_map
|
597
616
|
}
|
598
617
|
end
|
@@ -619,13 +638,6 @@ module ActiveRecord
|
|
619
638
|
@table_alias_length ||= query('SHOW max_identifier_length', 'SCHEMA')[0][0].to_i
|
620
639
|
end
|
621
640
|
|
622
|
-
def add_column_options!(sql, options)
|
623
|
-
if options[:array] || options[:column].try(:array)
|
624
|
-
sql << '[]'
|
625
|
-
end
|
626
|
-
super
|
627
|
-
end
|
628
|
-
|
629
641
|
# Set the authorized user for this session
|
630
642
|
def session_auth=(user)
|
631
643
|
clear_cache!
|
@@ -655,6 +667,10 @@ module ActiveRecord
|
|
655
667
|
@use_insert_returning
|
656
668
|
end
|
657
669
|
|
670
|
+
def valid_type?(type)
|
671
|
+
!native_database_types[type].nil?
|
672
|
+
end
|
673
|
+
|
658
674
|
protected
|
659
675
|
|
660
676
|
# Returns the version of the connected PostgreSQL server.
|
@@ -667,6 +683,8 @@ module ActiveRecord
|
|
667
683
|
UNIQUE_VIOLATION = "23505"
|
668
684
|
|
669
685
|
def translate_exception(exception, message)
|
686
|
+
return exception unless exception.respond_to?(:result)
|
687
|
+
|
670
688
|
case exception.result.try(:error_field, PGresult::PG_DIAG_SQLSTATE)
|
671
689
|
when UNIQUE_VIOLATION
|
672
690
|
RecordNotUnique.new(message, exception)
|
@@ -697,7 +715,14 @@ module ActiveRecord
|
|
697
715
|
|
698
716
|
# populate composite types
|
699
717
|
nodes.find_all { |row| OID::TYPE_MAP.key? row['typelem'].to_i }.each do |row|
|
700
|
-
|
718
|
+
if OID.registered_type? row['typname']
|
719
|
+
# this composite type is explicitly registered
|
720
|
+
vector = OID::NAMES[row['typname']]
|
721
|
+
else
|
722
|
+
# use the default for composite types
|
723
|
+
vector = OID::Vector.new row['typdelim'], OID::TYPE_MAP[row['typelem'].to_i]
|
724
|
+
end
|
725
|
+
|
701
726
|
OID::TYPE_MAP[row['oid'].to_i] = vector
|
702
727
|
end
|
703
728
|
|
@@ -884,8 +909,12 @@ module ActiveRecord
|
|
884
909
|
$1.strip if $1
|
885
910
|
end
|
886
911
|
|
887
|
-
def
|
888
|
-
TableDefinition.new
|
912
|
+
def create_table_definition(name, temporary, options)
|
913
|
+
TableDefinition.new native_database_types, name, temporary, options
|
914
|
+
end
|
915
|
+
|
916
|
+
def update_table_definition(table_name, base)
|
917
|
+
Table.new(table_name, base)
|
889
918
|
end
|
890
919
|
end
|
891
920
|
end
|