activerecord 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 +7 -0
- data/CHANGELOG.md +1372 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +218 -0
- data/examples/performance.rb +184 -0
- data/examples/simple.rb +14 -0
- data/lib/active_record.rb +173 -0
- data/lib/active_record/aggregations.rb +266 -0
- data/lib/active_record/association_relation.rb +22 -0
- data/lib/active_record/associations.rb +1724 -0
- data/lib/active_record/associations/alias_tracker.rb +87 -0
- data/lib/active_record/associations/association.rb +253 -0
- data/lib/active_record/associations/association_scope.rb +194 -0
- data/lib/active_record/associations/belongs_to_association.rb +111 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +40 -0
- data/lib/active_record/associations/builder/association.rb +149 -0
- data/lib/active_record/associations/builder/belongs_to.rb +116 -0
- data/lib/active_record/associations/builder/collection_association.rb +91 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +124 -0
- data/lib/active_record/associations/builder/has_many.rb +15 -0
- data/lib/active_record/associations/builder/has_one.rb +23 -0
- data/lib/active_record/associations/builder/singular_association.rb +38 -0
- data/lib/active_record/associations/collection_association.rb +634 -0
- data/lib/active_record/associations/collection_proxy.rb +1027 -0
- data/lib/active_record/associations/has_many_association.rb +184 -0
- data/lib/active_record/associations/has_many_through_association.rb +238 -0
- data/lib/active_record/associations/has_one_association.rb +105 -0
- data/lib/active_record/associations/has_one_through_association.rb +36 -0
- data/lib/active_record/associations/join_dependency.rb +282 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +122 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +22 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
- data/lib/active_record/associations/preloader.rb +203 -0
- data/lib/active_record/associations/preloader/association.rb +162 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +96 -0
- data/lib/active_record/associations/singular_association.rb +86 -0
- data/lib/active_record/associations/through_association.rb +96 -0
- data/lib/active_record/attribute.rb +149 -0
- data/lib/active_record/attribute_assignment.rb +212 -0
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods.rb +439 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +71 -0
- data/lib/active_record/attribute_methods/dirty.rb +181 -0
- data/lib/active_record/attribute_methods/primary_key.rb +128 -0
- data/lib/active_record/attribute_methods/query.rb +40 -0
- data/lib/active_record/attribute_methods/read.rb +103 -0
- data/lib/active_record/attribute_methods/serialization.rb +70 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
- data/lib/active_record/attribute_methods/write.rb +83 -0
- data/lib/active_record/attribute_set.rb +77 -0
- data/lib/active_record/attribute_set/builder.rb +86 -0
- data/lib/active_record/attributes.rb +139 -0
- data/lib/active_record/autosave_association.rb +439 -0
- data/lib/active_record/base.rb +317 -0
- data/lib/active_record/callbacks.rb +313 -0
- data/lib/active_record/coders/json.rb +13 -0
- data/lib/active_record/coders/yaml_column.rb +38 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +659 -0
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +67 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +373 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +133 -0
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +574 -0
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +991 -0
- data/lib/active_record/connection_adapters/abstract/transaction.rb +219 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -0
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +883 -0
- data/lib/active_record/connection_adapters/column.rb +82 -0
- data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +282 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +491 -0
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
- 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/quoting.rb +108 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +588 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +754 -0
- data/lib/active_record/connection_adapters/schema_cache.rb +94 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +628 -0
- data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
- data/lib/active_record/connection_handling.rb +132 -0
- data/lib/active_record/core.rb +566 -0
- data/lib/active_record/counter_cache.rb +175 -0
- data/lib/active_record/dynamic_matchers.rb +140 -0
- data/lib/active_record/enum.rb +198 -0
- data/lib/active_record/errors.rb +252 -0
- data/lib/active_record/explain.rb +38 -0
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +29 -0
- data/lib/active_record/fixture_set/file.rb +56 -0
- data/lib/active_record/fixtures.rb +1007 -0
- data/lib/active_record/gem_version.rb +15 -0
- data/lib/active_record/inheritance.rb +247 -0
- data/lib/active_record/integration.rb +113 -0
- data/lib/active_record/locale/en.yml +47 -0
- data/lib/active_record/locking/optimistic.rb +204 -0
- data/lib/active_record/locking/pessimistic.rb +77 -0
- data/lib/active_record/log_subscriber.rb +75 -0
- data/lib/active_record/migration.rb +1051 -0
- data/lib/active_record/migration/command_recorder.rb +197 -0
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/model_schema.rb +340 -0
- data/lib/active_record/nested_attributes.rb +548 -0
- data/lib/active_record/no_touching.rb +52 -0
- data/lib/active_record/null_relation.rb +81 -0
- data/lib/active_record/persistence.rb +532 -0
- data/lib/active_record/query_cache.rb +56 -0
- data/lib/active_record/querying.rb +68 -0
- data/lib/active_record/railtie.rb +162 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -0
- data/lib/active_record/railties/controller_runtime.rb +50 -0
- data/lib/active_record/railties/databases.rake +391 -0
- data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
- data/lib/active_record/readonly_attributes.rb +23 -0
- data/lib/active_record/reflection.rb +881 -0
- data/lib/active_record/relation.rb +681 -0
- data/lib/active_record/relation/batches.rb +138 -0
- data/lib/active_record/relation/calculations.rb +403 -0
- data/lib/active_record/relation/delegation.rb +140 -0
- data/lib/active_record/relation/finder_methods.rb +528 -0
- data/lib/active_record/relation/merger.rb +170 -0
- data/lib/active_record/relation/predicate_builder.rb +126 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +47 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
- data/lib/active_record/relation/query_methods.rb +1176 -0
- data/lib/active_record/relation/spawn_methods.rb +75 -0
- data/lib/active_record/result.rb +131 -0
- data/lib/active_record/runtime_registry.rb +22 -0
- data/lib/active_record/sanitization.rb +191 -0
- data/lib/active_record/schema.rb +64 -0
- data/lib/active_record/schema_dumper.rb +251 -0
- data/lib/active_record/schema_migration.rb +56 -0
- data/lib/active_record/scoping.rb +87 -0
- data/lib/active_record/scoping/default.rb +134 -0
- data/lib/active_record/scoping/named.rb +164 -0
- data/lib/active_record/serialization.rb +22 -0
- data/lib/active_record/serializers/xml_serializer.rb +193 -0
- data/lib/active_record/statement_cache.rb +111 -0
- data/lib/active_record/store.rb +205 -0
- data/lib/active_record/tasks/database_tasks.rb +296 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +145 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
- data/lib/active_record/timestamp.rb +121 -0
- data/lib/active_record/transactions.rb +417 -0
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/type.rb +23 -0
- 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/validations.rb +90 -0
- data/lib/active_record/validations/associated.rb +51 -0
- data/lib/active_record/validations/presence.rb +67 -0
- data/lib/active_record/validations/uniqueness.rb +229 -0
- data/lib/active_record/version.rb +8 -0
- data/lib/rails/generators/active_record.rb +17 -0
- data/lib/rails/generators/active_record/migration.rb +18 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +70 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +22 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +45 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +52 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +10 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
- metadata +309 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'active_support/core_ext/string/filters'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module PostgreSQL
|
6
|
+
module OID # :nodoc:
|
7
|
+
class Range < Type::Value # :nodoc:
|
8
|
+
attr_reader :subtype, :type
|
9
|
+
|
10
|
+
def initialize(subtype, type)
|
11
|
+
@subtype = subtype
|
12
|
+
@type = type
|
13
|
+
end
|
14
|
+
|
15
|
+
def type_cast_for_schema(value)
|
16
|
+
value.inspect.gsub('Infinity', '::Float::INFINITY')
|
17
|
+
end
|
18
|
+
|
19
|
+
def cast_value(value)
|
20
|
+
return if value == 'empty'
|
21
|
+
return value if value.is_a?(::Range)
|
22
|
+
|
23
|
+
extracted = extract_bounds(value)
|
24
|
+
from = type_cast_single extracted[:from]
|
25
|
+
to = type_cast_single extracted[:to]
|
26
|
+
|
27
|
+
if !infinity?(from) && extracted[:exclude_start]
|
28
|
+
if from.respond_to?(:succ)
|
29
|
+
from = from.succ
|
30
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
31
|
+
Excluding the beginning of a Range is only partialy supported
|
32
|
+
through `#succ`. This is not reliable and will be removed in
|
33
|
+
the future.
|
34
|
+
MSG
|
35
|
+
else
|
36
|
+
raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
::Range.new(from, to, extracted[:exclude_end])
|
40
|
+
end
|
41
|
+
|
42
|
+
def type_cast_for_database(value)
|
43
|
+
if value.is_a?(::Range)
|
44
|
+
from = type_cast_single_for_database(value.begin)
|
45
|
+
to = type_cast_single_for_database(value.end)
|
46
|
+
"[#{from},#{to}#{value.exclude_end? ? ')' : ']'}"
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def type_cast_single(value)
|
55
|
+
infinity?(value) ? value : @subtype.type_cast_from_database(value)
|
56
|
+
end
|
57
|
+
|
58
|
+
def type_cast_single_for_database(value)
|
59
|
+
infinity?(value) ? '' : @subtype.type_cast_for_database(value)
|
60
|
+
end
|
61
|
+
|
62
|
+
def extract_bounds(value)
|
63
|
+
from, to = value[1..-2].split(',')
|
64
|
+
{
|
65
|
+
from: (value[1] == ',' || from == '-infinity') ? @subtype.infinity(negative: true) : from,
|
66
|
+
to: (value[-2] == ',' || to == 'infinity') ? @subtype.infinity : to,
|
67
|
+
exclude_start: (value[0] == '('),
|
68
|
+
exclude_end: (value[-1] == ')')
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def infinity?(value)
|
73
|
+
value.respond_to?(:infinite?) && value.infinite?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
module OID # :nodoc:
|
5
|
+
# This class uses the data from PostgreSQL pg_type table to build
|
6
|
+
# the OID -> Type mapping.
|
7
|
+
# - OID is an integer representing the type.
|
8
|
+
# - Type is an OID::Type object.
|
9
|
+
# This class has side effects on the +store+ passed during initialization.
|
10
|
+
class TypeMapInitializer # :nodoc:
|
11
|
+
def initialize(store)
|
12
|
+
@store = store
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(records)
|
16
|
+
nodes = records.reject { |row| @store.key? row['oid'].to_i }
|
17
|
+
mapped, nodes = nodes.partition { |row| @store.key? row['typname'] }
|
18
|
+
ranges, nodes = nodes.partition { |row| row['typtype'] == 'r' }
|
19
|
+
enums, nodes = nodes.partition { |row| row['typtype'] == 'e' }
|
20
|
+
domains, nodes = nodes.partition { |row| row['typtype'] == 'd' }
|
21
|
+
arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' }
|
22
|
+
composites, nodes = nodes.partition { |row| row['typelem'] != '0' }
|
23
|
+
|
24
|
+
mapped.each { |row| register_mapped_type(row) }
|
25
|
+
enums.each { |row| register_enum_type(row) }
|
26
|
+
domains.each { |row| register_domain_type(row) }
|
27
|
+
arrays.each { |row| register_array_type(row) }
|
28
|
+
ranges.each { |row| register_range_type(row) }
|
29
|
+
composites.each { |row| register_composite_type(row) }
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def register_mapped_type(row)
|
34
|
+
alias_type row['oid'], row['typname']
|
35
|
+
end
|
36
|
+
|
37
|
+
def register_enum_type(row)
|
38
|
+
register row['oid'], OID::Enum.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def register_array_type(row)
|
42
|
+
register_with_subtype(row['oid'], row['typelem'].to_i) do |subtype|
|
43
|
+
OID::Array.new(subtype, row['typdelim'])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def register_range_type(row)
|
48
|
+
register_with_subtype(row['oid'], row['rngsubtype'].to_i) do |subtype|
|
49
|
+
OID::Range.new(subtype, row['typname'].to_sym)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def register_domain_type(row)
|
54
|
+
if base_type = @store.lookup(row["typbasetype"].to_i)
|
55
|
+
register row['oid'], base_type
|
56
|
+
else
|
57
|
+
warn "unknown base type (OID: #{row["typbasetype"]}) for domain #{row["typname"]}."
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def register_composite_type(row)
|
62
|
+
if subtype = @store.lookup(row['typelem'].to_i)
|
63
|
+
register row['oid'], OID::Vector.new(row['typdelim'], subtype)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def register(oid, oid_type = nil, &block)
|
68
|
+
oid = assert_valid_registration(oid, oid_type || block)
|
69
|
+
if block_given?
|
70
|
+
@store.register_type(oid, &block)
|
71
|
+
else
|
72
|
+
@store.register_type(oid, oid_type)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def alias_type(oid, target)
|
77
|
+
oid = assert_valid_registration(oid, target)
|
78
|
+
@store.alias_type(oid, target)
|
79
|
+
end
|
80
|
+
|
81
|
+
def register_with_subtype(oid, target_oid)
|
82
|
+
if @store.key?(target_oid)
|
83
|
+
register(oid) do |_, *args|
|
84
|
+
yield @store.lookup(target_oid, *args)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def assert_valid_registration(oid, oid_type)
|
90
|
+
raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
|
91
|
+
oid.to_i
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
module OID # :nodoc:
|
5
|
+
class Uuid < Type::Value # :nodoc:
|
6
|
+
ACCEPTABLE_UUID = %r{\A\{?([a-fA-F0-9]{4}-?){8}\}?\z}x
|
7
|
+
|
8
|
+
alias_method :type_cast_for_database, :type_cast_from_database
|
9
|
+
|
10
|
+
def type
|
11
|
+
:uuid
|
12
|
+
end
|
13
|
+
|
14
|
+
def type_cast(value)
|
15
|
+
value.to_s[ACCEPTABLE_UUID, 0]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
module OID # :nodoc:
|
5
|
+
class Vector < Type::Value # :nodoc:
|
6
|
+
attr_reader :delim, :subtype
|
7
|
+
|
8
|
+
# +delim+ corresponds to the `typdelim` column in the pg_types
|
9
|
+
# table. +subtype+ is derived from the `typelem` column in the
|
10
|
+
# pg_types table.
|
11
|
+
def initialize(delim, subtype)
|
12
|
+
@delim = delim
|
13
|
+
@subtype = subtype
|
14
|
+
end
|
15
|
+
|
16
|
+
# FIXME: this should probably split on +delim+ and use +subtype+
|
17
|
+
# to cast the values. Unfortunately, the current Rails behavior
|
18
|
+
# is to just return the string.
|
19
|
+
def type_cast(value)
|
20
|
+
value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
module OID # :nodoc:
|
5
|
+
class Xml < Type::String # :nodoc:
|
6
|
+
def type
|
7
|
+
:xml
|
8
|
+
end
|
9
|
+
|
10
|
+
def type_cast_for_database(value)
|
11
|
+
return unless value
|
12
|
+
Data.new(super)
|
13
|
+
end
|
14
|
+
|
15
|
+
class Data # :nodoc:
|
16
|
+
def initialize(value)
|
17
|
+
@value = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
@value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
module Quoting
|
5
|
+
# Escapes binary strings for bytea input to the database.
|
6
|
+
def escape_bytea(value)
|
7
|
+
@connection.escape_bytea(value) if value
|
8
|
+
end
|
9
|
+
|
10
|
+
# Unescapes bytea output from a database to the binary string it represents.
|
11
|
+
# NOTE: This is NOT an inverse of escape_bytea! This is only to be used
|
12
|
+
# on escaped binary output from database drive.
|
13
|
+
def unescape_bytea(value)
|
14
|
+
@connection.unescape_bytea(value) if value
|
15
|
+
end
|
16
|
+
|
17
|
+
# Quotes strings for use in SQL input.
|
18
|
+
def quote_string(s) #:nodoc:
|
19
|
+
@connection.escape(s)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Checks the following cases:
|
23
|
+
#
|
24
|
+
# - table_name
|
25
|
+
# - "table.name"
|
26
|
+
# - schema_name.table_name
|
27
|
+
# - schema_name."table.name"
|
28
|
+
# - "schema.name".table_name
|
29
|
+
# - "schema.name"."table.name"
|
30
|
+
def quote_table_name(name)
|
31
|
+
Utils.extract_schema_qualified_name(name.to_s).quoted
|
32
|
+
end
|
33
|
+
|
34
|
+
def quote_table_name_for_assignment(table, attr)
|
35
|
+
quote_column_name(attr)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Quotes column names for use in SQL queries.
|
39
|
+
def quote_column_name(name) #:nodoc:
|
40
|
+
PGconn.quote_ident(name.to_s)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Quote date/time values for use in SQL input. Includes microseconds
|
44
|
+
# if the value is a Time responding to usec.
|
45
|
+
def quoted_date(value) #:nodoc:
|
46
|
+
result = super
|
47
|
+
if value.acts_like?(:time) && value.respond_to?(:usec)
|
48
|
+
result = "#{result}.#{sprintf("%06d", value.usec)}"
|
49
|
+
end
|
50
|
+
|
51
|
+
if value.year <= 0
|
52
|
+
bce_year = format("%04d", -value.year + 1)
|
53
|
+
result = result.sub(/^-?\d+/, bce_year) + " BC"
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
# Does not quote function default values for UUID columns
|
59
|
+
def quote_default_value(value, column) #:nodoc:
|
60
|
+
if column.type == :uuid && value =~ /\(\)/
|
61
|
+
value
|
62
|
+
else
|
63
|
+
quote(value, column)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def _quote(value)
|
70
|
+
case value
|
71
|
+
when Type::Binary::Data
|
72
|
+
"'#{escape_bytea(value.to_s)}'"
|
73
|
+
when OID::Xml::Data
|
74
|
+
"xml '#{quote_string(value.to_s)}'"
|
75
|
+
when OID::Bit::Data
|
76
|
+
if value.binary?
|
77
|
+
"B'#{value}'"
|
78
|
+
elsif value.hex?
|
79
|
+
"X'#{value}'"
|
80
|
+
end
|
81
|
+
when Float
|
82
|
+
if value.infinite? || value.nan?
|
83
|
+
"'#{value}'"
|
84
|
+
else
|
85
|
+
super
|
86
|
+
end
|
87
|
+
else
|
88
|
+
super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def _type_cast(value)
|
93
|
+
case value
|
94
|
+
when Type::Binary::Data
|
95
|
+
# Return a bind param hash with format as binary.
|
96
|
+
# See http://deveiate.org/code/pg/PGconn.html#method-i-exec_prepared-doc
|
97
|
+
# for more information
|
98
|
+
{ value: value.to_s, format: 1 }
|
99
|
+
when OID::Xml::Data, OID::Bit::Data
|
100
|
+
value.to_s
|
101
|
+
else
|
102
|
+
super
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
module ReferentialIntegrity # :nodoc:
|
5
|
+
def supports_disable_referential_integrity? # :nodoc:
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def disable_referential_integrity # :nodoc:
|
10
|
+
if supports_disable_referential_integrity?
|
11
|
+
begin
|
12
|
+
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
|
13
|
+
rescue
|
14
|
+
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER USER" }.join(";"))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
yield
|
18
|
+
ensure
|
19
|
+
if supports_disable_referential_integrity?
|
20
|
+
begin
|
21
|
+
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
|
22
|
+
rescue
|
23
|
+
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER USER" }.join(";"))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
module ColumnMethods
|
5
|
+
def xml(*args)
|
6
|
+
options = args.extract_options!
|
7
|
+
column(args[0], :xml, options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def tsvector(*args)
|
11
|
+
options = args.extract_options!
|
12
|
+
column(args[0], :tsvector, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def int4range(name, options = {})
|
16
|
+
column(name, :int4range, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def int8range(name, options = {})
|
20
|
+
column(name, :int8range, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def tsrange(name, options = {})
|
24
|
+
column(name, :tsrange, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def tstzrange(name, options = {})
|
28
|
+
column(name, :tstzrange, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def numrange(name, options = {})
|
32
|
+
column(name, :numrange, options)
|
33
|
+
end
|
34
|
+
|
35
|
+
def daterange(name, options = {})
|
36
|
+
column(name, :daterange, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def hstore(name, options = {})
|
40
|
+
column(name, :hstore, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def ltree(name, options = {})
|
44
|
+
column(name, :ltree, options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def inet(name, options = {})
|
48
|
+
column(name, :inet, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def cidr(name, options = {})
|
52
|
+
column(name, :cidr, options)
|
53
|
+
end
|
54
|
+
|
55
|
+
def macaddr(name, options = {})
|
56
|
+
column(name, :macaddr, options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def uuid(name, options = {})
|
60
|
+
column(name, :uuid, options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def json(name, options = {})
|
64
|
+
column(name, :json, options)
|
65
|
+
end
|
66
|
+
|
67
|
+
def jsonb(name, options = {})
|
68
|
+
column(name, :jsonb, options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def citext(name, options = {})
|
72
|
+
column(name, :citext, options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def point(name, options = {})
|
76
|
+
column(name, :point, options)
|
77
|
+
end
|
78
|
+
|
79
|
+
def bit(name, options)
|
80
|
+
column(name, :bit, options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def bit_varying(name, options)
|
84
|
+
column(name, :bit_varying, options)
|
85
|
+
end
|
86
|
+
|
87
|
+
def money(name, options)
|
88
|
+
column(name, :money, options)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
|
93
|
+
attr_accessor :array
|
94
|
+
end
|
95
|
+
|
96
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
97
|
+
include ColumnMethods
|
98
|
+
|
99
|
+
# Defines the primary key field.
|
100
|
+
# Use of the native PostgreSQL UUID type is supported, and can be used
|
101
|
+
# by defining your tables as such:
|
102
|
+
#
|
103
|
+
# create_table :stuffs, id: :uuid do |t|
|
104
|
+
# t.string :content
|
105
|
+
# t.timestamps
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# By default, this will use the +uuid_generate_v4()+ function from the
|
109
|
+
# +uuid-ossp+ extension, which MUST be enabled on your database. To enable
|
110
|
+
# the +uuid-ossp+ extension, you can use the +enable_extension+ method in your
|
111
|
+
# migrations. To use a UUID primary key without +uuid-ossp+ enabled, you can
|
112
|
+
# set the +:default+ option to +nil+:
|
113
|
+
#
|
114
|
+
# create_table :stuffs, id: false do |t|
|
115
|
+
# t.primary_key :id, :uuid, default: nil
|
116
|
+
# t.uuid :foo_id
|
117
|
+
# t.timestamps
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# You may also pass a different UUID generation function from +uuid-ossp+
|
121
|
+
# or another library.
|
122
|
+
#
|
123
|
+
# Note that setting the UUID primary key default value to +nil+ will
|
124
|
+
# require you to assure that you always provide a UUID value before saving
|
125
|
+
# a record (as primary keys cannot be +nil+). This might be done via the
|
126
|
+
# +SecureRandom.uuid+ method and a +before_save+ callback, for instance.
|
127
|
+
def primary_key(name, type = :primary_key, options = {})
|
128
|
+
return super unless type == :uuid
|
129
|
+
options[:default] = options.fetch(:default, 'uuid_generate_v4()')
|
130
|
+
options[:primary_key] = true
|
131
|
+
column name, type, options
|
132
|
+
end
|
133
|
+
|
134
|
+
def new_column_definition(name, type, options) # :nodoc:
|
135
|
+
column = super
|
136
|
+
column.array = options[:array]
|
137
|
+
column
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def create_column_definition(name, type)
|
143
|
+
PostgreSQL::ColumnDefinition.new name, type
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
148
|
+
include ColumnMethods
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|