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.

Files changed (221) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1372 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +218 -0
  5. data/examples/performance.rb +184 -0
  6. data/examples/simple.rb +14 -0
  7. data/lib/active_record.rb +173 -0
  8. data/lib/active_record/aggregations.rb +266 -0
  9. data/lib/active_record/association_relation.rb +22 -0
  10. data/lib/active_record/associations.rb +1724 -0
  11. data/lib/active_record/associations/alias_tracker.rb +87 -0
  12. data/lib/active_record/associations/association.rb +253 -0
  13. data/lib/active_record/associations/association_scope.rb +194 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +111 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +40 -0
  16. data/lib/active_record/associations/builder/association.rb +149 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +116 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +91 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +124 -0
  20. data/lib/active_record/associations/builder/has_many.rb +15 -0
  21. data/lib/active_record/associations/builder/has_one.rb +23 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +38 -0
  23. data/lib/active_record/associations/collection_association.rb +634 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1027 -0
  25. data/lib/active_record/associations/has_many_association.rb +184 -0
  26. data/lib/active_record/associations/has_many_through_association.rb +238 -0
  27. data/lib/active_record/associations/has_one_association.rb +105 -0
  28. data/lib/active_record/associations/has_one_through_association.rb +36 -0
  29. data/lib/active_record/associations/join_dependency.rb +282 -0
  30. data/lib/active_record/associations/join_dependency/join_association.rb +122 -0
  31. data/lib/active_record/associations/join_dependency/join_base.rb +22 -0
  32. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  33. data/lib/active_record/associations/preloader.rb +203 -0
  34. data/lib/active_record/associations/preloader/association.rb +162 -0
  35. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  36. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  37. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  38. data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
  39. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  40. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  41. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  42. data/lib/active_record/associations/preloader/through_association.rb +96 -0
  43. data/lib/active_record/associations/singular_association.rb +86 -0
  44. data/lib/active_record/associations/through_association.rb +96 -0
  45. data/lib/active_record/attribute.rb +149 -0
  46. data/lib/active_record/attribute_assignment.rb +212 -0
  47. data/lib/active_record/attribute_decorators.rb +66 -0
  48. data/lib/active_record/attribute_methods.rb +439 -0
  49. data/lib/active_record/attribute_methods/before_type_cast.rb +71 -0
  50. data/lib/active_record/attribute_methods/dirty.rb +181 -0
  51. data/lib/active_record/attribute_methods/primary_key.rb +128 -0
  52. data/lib/active_record/attribute_methods/query.rb +40 -0
  53. data/lib/active_record/attribute_methods/read.rb +103 -0
  54. data/lib/active_record/attribute_methods/serialization.rb +70 -0
  55. data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
  56. data/lib/active_record/attribute_methods/write.rb +83 -0
  57. data/lib/active_record/attribute_set.rb +77 -0
  58. data/lib/active_record/attribute_set/builder.rb +86 -0
  59. data/lib/active_record/attributes.rb +139 -0
  60. data/lib/active_record/autosave_association.rb +439 -0
  61. data/lib/active_record/base.rb +317 -0
  62. data/lib/active_record/callbacks.rb +313 -0
  63. data/lib/active_record/coders/json.rb +13 -0
  64. data/lib/active_record/coders/yaml_column.rb +38 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +659 -0
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +67 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +373 -0
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -0
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +133 -0
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +574 -0
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +991 -0
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +219 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -0
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +883 -0
  78. data/lib/active_record/connection_adapters/column.rb +82 -0
  79. data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +282 -0
  81. data/lib/active_record/connection_adapters/mysql_adapter.rb +491 -0
  82. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +99 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +97 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  111. data/lib/active_record/connection_adapters/postgresql/quoting.rb +108 -0
  112. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +588 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +754 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +94 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +628 -0
  119. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  120. data/lib/active_record/connection_handling.rb +132 -0
  121. data/lib/active_record/core.rb +566 -0
  122. data/lib/active_record/counter_cache.rb +175 -0
  123. data/lib/active_record/dynamic_matchers.rb +140 -0
  124. data/lib/active_record/enum.rb +198 -0
  125. data/lib/active_record/errors.rb +252 -0
  126. data/lib/active_record/explain.rb +38 -0
  127. data/lib/active_record/explain_registry.rb +30 -0
  128. data/lib/active_record/explain_subscriber.rb +29 -0
  129. data/lib/active_record/fixture_set/file.rb +56 -0
  130. data/lib/active_record/fixtures.rb +1007 -0
  131. data/lib/active_record/gem_version.rb +15 -0
  132. data/lib/active_record/inheritance.rb +247 -0
  133. data/lib/active_record/integration.rb +113 -0
  134. data/lib/active_record/locale/en.yml +47 -0
  135. data/lib/active_record/locking/optimistic.rb +204 -0
  136. data/lib/active_record/locking/pessimistic.rb +77 -0
  137. data/lib/active_record/log_subscriber.rb +75 -0
  138. data/lib/active_record/migration.rb +1051 -0
  139. data/lib/active_record/migration/command_recorder.rb +197 -0
  140. data/lib/active_record/migration/join_table.rb +15 -0
  141. data/lib/active_record/model_schema.rb +340 -0
  142. data/lib/active_record/nested_attributes.rb +548 -0
  143. data/lib/active_record/no_touching.rb +52 -0
  144. data/lib/active_record/null_relation.rb +81 -0
  145. data/lib/active_record/persistence.rb +532 -0
  146. data/lib/active_record/query_cache.rb +56 -0
  147. data/lib/active_record/querying.rb +68 -0
  148. data/lib/active_record/railtie.rb +162 -0
  149. data/lib/active_record/railties/console_sandbox.rb +5 -0
  150. data/lib/active_record/railties/controller_runtime.rb +50 -0
  151. data/lib/active_record/railties/databases.rake +391 -0
  152. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  153. data/lib/active_record/readonly_attributes.rb +23 -0
  154. data/lib/active_record/reflection.rb +881 -0
  155. data/lib/active_record/relation.rb +681 -0
  156. data/lib/active_record/relation/batches.rb +138 -0
  157. data/lib/active_record/relation/calculations.rb +403 -0
  158. data/lib/active_record/relation/delegation.rb +140 -0
  159. data/lib/active_record/relation/finder_methods.rb +528 -0
  160. data/lib/active_record/relation/merger.rb +170 -0
  161. data/lib/active_record/relation/predicate_builder.rb +126 -0
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +47 -0
  163. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  164. data/lib/active_record/relation/query_methods.rb +1176 -0
  165. data/lib/active_record/relation/spawn_methods.rb +75 -0
  166. data/lib/active_record/result.rb +131 -0
  167. data/lib/active_record/runtime_registry.rb +22 -0
  168. data/lib/active_record/sanitization.rb +191 -0
  169. data/lib/active_record/schema.rb +64 -0
  170. data/lib/active_record/schema_dumper.rb +251 -0
  171. data/lib/active_record/schema_migration.rb +56 -0
  172. data/lib/active_record/scoping.rb +87 -0
  173. data/lib/active_record/scoping/default.rb +134 -0
  174. data/lib/active_record/scoping/named.rb +164 -0
  175. data/lib/active_record/serialization.rb +22 -0
  176. data/lib/active_record/serializers/xml_serializer.rb +193 -0
  177. data/lib/active_record/statement_cache.rb +111 -0
  178. data/lib/active_record/store.rb +205 -0
  179. data/lib/active_record/tasks/database_tasks.rb +296 -0
  180. data/lib/active_record/tasks/mysql_database_tasks.rb +145 -0
  181. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  182. data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
  183. data/lib/active_record/timestamp.rb +121 -0
  184. data/lib/active_record/transactions.rb +417 -0
  185. data/lib/active_record/translation.rb +22 -0
  186. data/lib/active_record/type.rb +23 -0
  187. data/lib/active_record/type/big_integer.rb +13 -0
  188. data/lib/active_record/type/binary.rb +50 -0
  189. data/lib/active_record/type/boolean.rb +30 -0
  190. data/lib/active_record/type/date.rb +46 -0
  191. data/lib/active_record/type/date_time.rb +43 -0
  192. data/lib/active_record/type/decimal.rb +40 -0
  193. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  194. data/lib/active_record/type/decorator.rb +14 -0
  195. data/lib/active_record/type/float.rb +19 -0
  196. data/lib/active_record/type/hash_lookup_type_map.rb +17 -0
  197. data/lib/active_record/type/integer.rb +55 -0
  198. data/lib/active_record/type/mutable.rb +16 -0
  199. data/lib/active_record/type/numeric.rb +36 -0
  200. data/lib/active_record/type/serialized.rb +56 -0
  201. data/lib/active_record/type/string.rb +36 -0
  202. data/lib/active_record/type/text.rb +11 -0
  203. data/lib/active_record/type/time.rb +26 -0
  204. data/lib/active_record/type/time_value.rb +38 -0
  205. data/lib/active_record/type/type_map.rb +64 -0
  206. data/lib/active_record/type/unsigned_integer.rb +15 -0
  207. data/lib/active_record/type/value.rb +101 -0
  208. data/lib/active_record/validations.rb +90 -0
  209. data/lib/active_record/validations/associated.rb +51 -0
  210. data/lib/active_record/validations/presence.rb +67 -0
  211. data/lib/active_record/validations/uniqueness.rb +229 -0
  212. data/lib/active_record/version.rb +8 -0
  213. data/lib/rails/generators/active_record.rb +17 -0
  214. data/lib/rails/generators/active_record/migration.rb +18 -0
  215. data/lib/rails/generators/active_record/migration/migration_generator.rb +70 -0
  216. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +22 -0
  217. data/lib/rails/generators/active_record/migration/templates/migration.rb +45 -0
  218. data/lib/rails/generators/active_record/model/model_generator.rb +52 -0
  219. data/lib/rails/generators/active_record/model/templates/model.rb +10 -0
  220. data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
  221. 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,15 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module PostgreSQL
4
+ module OID # :nodoc:
5
+ class SpecializedString < Type::String # :nodoc:
6
+ attr_reader :type
7
+
8
+ def initialize(type)
9
+ @type = type
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module PostgreSQL
4
+ module OID # :nodoc:
5
+ class Time < Type::Time # :nodoc:
6
+ include Infinity
7
+ end
8
+ end
9
+ end
10
+ end
11
+ 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