activerecord 3.2.19 → 5.0.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 (264) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1715 -604
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +40 -45
  5. data/examples/performance.rb +33 -22
  6. data/examples/simple.rb +3 -4
  7. data/lib/active_record/aggregations.rb +76 -51
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +54 -40
  10. data/lib/active_record/associations/association.rb +76 -56
  11. data/lib/active_record/associations/association_scope.rb +125 -93
  12. data/lib/active_record/associations/belongs_to_association.rb +57 -28
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  14. data/lib/active_record/associations/builder/association.rb +120 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +115 -62
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -53
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +117 -43
  18. data/lib/active_record/associations/builder/has_many.rb +9 -65
  19. data/lib/active_record/associations/builder/has_one.rb +18 -52
  20. data/lib/active_record/associations/builder/singular_association.rb +18 -19
  21. data/lib/active_record/associations/collection_association.rb +268 -186
  22. data/lib/active_record/associations/collection_proxy.rb +1003 -63
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +81 -41
  25. data/lib/active_record/associations/has_many_through_association.rb +76 -55
  26. data/lib/active_record/associations/has_one_association.rb +51 -21
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +83 -108
  29. data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
  31. data/lib/active_record/associations/join_dependency.rb +239 -155
  32. data/lib/active_record/associations/preloader/association.rb +97 -62
  33. data/lib/active_record/associations/preloader/collection_association.rb +2 -8
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +75 -33
  38. data/lib/active_record/associations/preloader.rb +111 -79
  39. data/lib/active_record/associations/singular_association.rb +35 -13
  40. data/lib/active_record/associations/through_association.rb +41 -19
  41. data/lib/active_record/associations.rb +727 -501
  42. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  43. data/lib/active_record/attribute.rb +213 -0
  44. data/lib/active_record/attribute_assignment.rb +32 -162
  45. data/lib/active_record/attribute_decorators.rb +67 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  47. data/lib/active_record/attribute_methods/dirty.rb +101 -61
  48. data/lib/active_record/attribute_methods/primary_key.rb +50 -36
  49. data/lib/active_record/attribute_methods/query.rb +7 -6
  50. data/lib/active_record/attribute_methods/read.rb +56 -117
  51. data/lib/active_record/attribute_methods/serialization.rb +43 -96
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +93 -42
  53. data/lib/active_record/attribute_methods/write.rb +34 -45
  54. data/lib/active_record/attribute_methods.rb +333 -144
  55. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  56. data/lib/active_record/attribute_set/builder.rb +108 -0
  57. data/lib/active_record/attribute_set.rb +108 -0
  58. data/lib/active_record/attributes.rb +265 -0
  59. data/lib/active_record/autosave_association.rb +285 -223
  60. data/lib/active_record/base.rb +95 -490
  61. data/lib/active_record/callbacks.rb +95 -61
  62. data/lib/active_record/coders/json.rb +13 -0
  63. data/lib/active_record/coders/yaml_column.rb +28 -19
  64. data/lib/active_record/collection_cache_key.rb +40 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +724 -277
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -192
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -26
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +140 -57
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +147 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +419 -276
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +105 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +963 -276
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +232 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +397 -106
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +643 -342
  78. data/lib/active_record/connection_adapters/column.rb +30 -259
  79. data/lib/active_record/connection_adapters/connection_specification.rb +263 -0
  80. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  81. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  82. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  83. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  84. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  89. data/lib/active_record/connection_adapters/mysql2_adapter.rb +47 -196
  90. data/lib/active_record/connection_adapters/postgresql/column.rb +15 -0
  91. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +170 -0
  92. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +70 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +48 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +21 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +10 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +39 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +93 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid.rb +31 -0
  115. data/lib/active_record/connection_adapters/postgresql/quoting.rb +116 -0
  116. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +49 -0
  117. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +180 -0
  118. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  119. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +682 -0
  120. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  121. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  122. data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -1039
  123. data/lib/active_record/connection_adapters/schema_cache.rb +74 -36
  124. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  125. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +538 -24
  129. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  130. data/lib/active_record/connection_handling.rb +155 -0
  131. data/lib/active_record/core.rb +561 -0
  132. data/lib/active_record/counter_cache.rb +146 -105
  133. data/lib/active_record/dynamic_matchers.rb +101 -64
  134. data/lib/active_record/enum.rb +234 -0
  135. data/lib/active_record/errors.rb +153 -56
  136. data/lib/active_record/explain.rb +15 -63
  137. data/lib/active_record/explain_registry.rb +30 -0
  138. data/lib/active_record/explain_subscriber.rb +10 -6
  139. data/lib/active_record/fixture_set/file.rb +77 -0
  140. data/lib/active_record/fixtures.rb +355 -232
  141. data/lib/active_record/gem_version.rb +15 -0
  142. data/lib/active_record/inheritance.rb +144 -79
  143. data/lib/active_record/integration.rb +66 -13
  144. data/lib/active_record/internal_metadata.rb +56 -0
  145. data/lib/active_record/legacy_yaml_adapter.rb +46 -0
  146. data/lib/active_record/locale/en.yml +9 -1
  147. data/lib/active_record/locking/optimistic.rb +77 -56
  148. data/lib/active_record/locking/pessimistic.rb +6 -6
  149. data/lib/active_record/log_subscriber.rb +53 -28
  150. data/lib/active_record/migration/command_recorder.rb +166 -33
  151. data/lib/active_record/migration/compatibility.rb +126 -0
  152. data/lib/active_record/migration/join_table.rb +15 -0
  153. data/lib/active_record/migration.rb +792 -264
  154. data/lib/active_record/model_schema.rb +192 -130
  155. data/lib/active_record/nested_attributes.rb +238 -145
  156. data/lib/active_record/no_touching.rb +52 -0
  157. data/lib/active_record/null_relation.rb +89 -0
  158. data/lib/active_record/persistence.rb +357 -157
  159. data/lib/active_record/query_cache.rb +22 -43
  160. data/lib/active_record/querying.rb +34 -23
  161. data/lib/active_record/railtie.rb +88 -48
  162. data/lib/active_record/railties/console_sandbox.rb +3 -4
  163. data/lib/active_record/railties/controller_runtime.rb +5 -4
  164. data/lib/active_record/railties/databases.rake +170 -422
  165. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  166. data/lib/active_record/readonly_attributes.rb +2 -5
  167. data/lib/active_record/reflection.rb +715 -189
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  169. data/lib/active_record/relation/batches.rb +203 -50
  170. data/lib/active_record/relation/calculations.rb +203 -194
  171. data/lib/active_record/relation/delegation.rb +103 -25
  172. data/lib/active_record/relation/finder_methods.rb +457 -261
  173. data/lib/active_record/relation/from_clause.rb +32 -0
  174. data/lib/active_record/relation/merger.rb +167 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +43 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  179. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  180. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  181. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  182. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  183. data/lib/active_record/relation/predicate_builder.rb +153 -48
  184. data/lib/active_record/relation/query_attribute.rb +19 -0
  185. data/lib/active_record/relation/query_methods.rb +1019 -194
  186. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  187. data/lib/active_record/relation/spawn_methods.rb +46 -150
  188. data/lib/active_record/relation/where_clause.rb +174 -0
  189. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  190. data/lib/active_record/relation.rb +450 -245
  191. data/lib/active_record/result.rb +104 -12
  192. data/lib/active_record/runtime_registry.rb +22 -0
  193. data/lib/active_record/sanitization.rb +120 -94
  194. data/lib/active_record/schema.rb +28 -18
  195. data/lib/active_record/schema_dumper.rb +141 -74
  196. data/lib/active_record/schema_migration.rb +50 -0
  197. data/lib/active_record/scoping/default.rb +64 -57
  198. data/lib/active_record/scoping/named.rb +93 -108
  199. data/lib/active_record/scoping.rb +73 -121
  200. data/lib/active_record/secure_token.rb +38 -0
  201. data/lib/active_record/serialization.rb +7 -5
  202. data/lib/active_record/statement_cache.rb +113 -0
  203. data/lib/active_record/store.rb +173 -15
  204. data/lib/active_record/suppressor.rb +58 -0
  205. data/lib/active_record/table_metadata.rb +68 -0
  206. data/lib/active_record/tasks/database_tasks.rb +313 -0
  207. data/lib/active_record/tasks/mysql_database_tasks.rb +151 -0
  208. data/lib/active_record/tasks/postgresql_database_tasks.rb +110 -0
  209. data/lib/active_record/tasks/sqlite_database_tasks.rb +59 -0
  210. data/lib/active_record/timestamp.rb +42 -24
  211. data/lib/active_record/touch_later.rb +58 -0
  212. data/lib/active_record/transactions.rb +233 -105
  213. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  214. data/lib/active_record/type/date.rb +7 -0
  215. data/lib/active_record/type/date_time.rb +7 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  217. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  218. data/lib/active_record/type/internal/timezone.rb +15 -0
  219. data/lib/active_record/type/serialized.rb +63 -0
  220. data/lib/active_record/type/time.rb +20 -0
  221. data/lib/active_record/type/type_map.rb +64 -0
  222. data/lib/active_record/type.rb +72 -0
  223. data/lib/active_record/type_caster/connection.rb +29 -0
  224. data/lib/active_record/type_caster/map.rb +19 -0
  225. data/lib/active_record/type_caster.rb +7 -0
  226. data/lib/active_record/validations/absence.rb +23 -0
  227. data/lib/active_record/validations/associated.rb +33 -18
  228. data/lib/active_record/validations/length.rb +24 -0
  229. data/lib/active_record/validations/presence.rb +66 -0
  230. data/lib/active_record/validations/uniqueness.rb +128 -68
  231. data/lib/active_record/validations.rb +48 -40
  232. data/lib/active_record/version.rb +5 -7
  233. data/lib/active_record.rb +71 -47
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +56 -8
  235. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +24 -0
  236. data/lib/rails/generators/active_record/migration/templates/migration.rb +28 -16
  237. data/lib/rails/generators/active_record/migration.rb +18 -8
  238. data/lib/rails/generators/active_record/model/model_generator.rb +38 -16
  239. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  240. data/lib/rails/generators/active_record/model/templates/model.rb +7 -6
  241. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  242. data/lib/rails/generators/active_record.rb +3 -11
  243. metadata +188 -134
  244. data/examples/associations.png +0 -0
  245. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  246. data/lib/active_record/associations/join_helper.rb +0 -55
  247. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  248. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  249. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  250. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  251. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  252. data/lib/active_record/dynamic_finder_match.rb +0 -68
  253. data/lib/active_record/dynamic_scope_match.rb +0 -23
  254. data/lib/active_record/fixtures/file.rb +0 -65
  255. data/lib/active_record/identity_map.rb +0 -162
  256. data/lib/active_record/observer.rb +0 -121
  257. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  258. data/lib/active_record/session_store.rb +0 -360
  259. data/lib/active_record/test_case.rb +0 -73
  260. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  261. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  262. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  263. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  264. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,107 +1,35 @@
1
- require 'set'
2
-
3
1
  module ActiveRecord
4
2
  # :stopdoc:
5
3
  module ConnectionAdapters
6
4
  # An abstract definition of a column in a table.
7
5
  class Column
8
- TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
9
- FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set
10
-
11
- module Format
12
- ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
13
- ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
14
- end
6
+ attr_reader :name, :default, :sql_type_metadata, :null, :table_name, :default_function, :collation, :comment
15
7
 
16
- attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale
17
- attr_accessor :primary, :coder
18
-
19
- alias :encoded? :coder
8
+ delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
20
9
 
21
10
  # Instantiates a new column in the table.
22
11
  #
23
- # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int(11)</tt>.
12
+ # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int</tt>.
24
13
  # +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
25
- # +sql_type+ is used to extract the column's length, if necessary. For example +60+ in
26
- # <tt>company_name varchar(60)</tt>.
27
- # It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
14
+ # +sql_type_metadata+ is various information about the type of the column
28
15
  # +null+ determines if this column allows +NULL+ values.
29
- def initialize(name, default, sql_type = nil, null = true)
30
- @name = name
31
- @sql_type = sql_type
32
- @null = null
33
- @limit = extract_limit(sql_type)
34
- @precision = extract_precision(sql_type)
35
- @scale = extract_scale(sql_type)
36
- @type = simplified_type(sql_type)
37
- @default = extract_default(default)
38
- @primary = nil
39
- @coder = nil
40
- end
41
-
42
- # Returns +true+ if the column is either of type string or text.
43
- def text?
44
- type == :string || type == :text
45
- end
46
-
47
- # Returns +true+ if the column is either of type integer, float or decimal.
48
- def number?
49
- type == :integer || type == :float || type == :decimal
16
+ def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
17
+ @name = name.freeze
18
+ @table_name = table_name
19
+ @sql_type_metadata = sql_type_metadata
20
+ @null = null
21
+ @default = default
22
+ @default_function = default_function
23
+ @collation = collation
24
+ @comment = comment
50
25
  end
51
26
 
52
27
  def has_default?
53
- !default.nil?
54
- end
55
-
56
- # Returns the Ruby class that corresponds to the abstract data type.
57
- def klass
58
- case type
59
- when :integer then Fixnum
60
- when :float then Float
61
- when :decimal then BigDecimal
62
- when :datetime, :timestamp, :time then Time
63
- when :date then Date
64
- when :text, :string, :binary then String
65
- when :boolean then Object
66
- end
28
+ !default.nil? || default_function
67
29
  end
68
30
 
69
- # Casts value (which is a String) to an appropriate instance.
70
- def type_cast(value)
71
- return nil if value.nil?
72
- return coder.load(value) if encoded?
73
-
74
- klass = self.class
75
-
76
- case type
77
- when :string, :text then value
78
- when :integer then klass.value_to_integer(value)
79
- when :float then value.to_f
80
- when :decimal then klass.value_to_decimal(value)
81
- when :datetime, :timestamp then klass.string_to_time(value)
82
- when :time then klass.string_to_dummy_time(value)
83
- when :date then klass.string_to_date(value)
84
- when :binary then klass.binary_to_string(value)
85
- when :boolean then klass.value_to_boolean(value)
86
- else value
87
- end
88
- end
89
-
90
- def type_cast_code(var_name)
91
- klass = self.class.name
92
-
93
- case type
94
- when :string, :text then var_name
95
- when :integer then "#{klass}.value_to_integer(#{var_name})"
96
- when :float then "#{var_name}.to_f"
97
- when :decimal then "#{klass}.value_to_decimal(#{var_name})"
98
- when :datetime, :timestamp then "#{klass}.string_to_time(#{var_name})"
99
- when :time then "#{klass}.string_to_dummy_time(#{var_name})"
100
- when :date then "#{klass}.string_to_date(#{var_name})"
101
- when :binary then "#{klass}.binary_to_string(#{var_name})"
102
- when :boolean then "#{klass}.value_to_boolean(#{var_name})"
103
- else var_name
104
- end
31
+ def bigint?
32
+ /\Abigint\b/ === sql_type
105
33
  end
106
34
 
107
35
  # Returns the human name of the column name.
@@ -112,184 +40,27 @@ module ActiveRecord
112
40
  Base.human_attribute_name(@name)
113
41
  end
114
42
 
115
- def extract_default(default)
116
- type_cast(default)
43
+ def ==(other)
44
+ other.is_a?(Column) &&
45
+ attributes_for_hash == other.attributes_for_hash
117
46
  end
47
+ alias :eql? :==
118
48
 
119
- # Used to convert from Strings to BLOBs
120
- def string_to_binary(value)
121
- self.class.string_to_binary(value)
49
+ def hash
50
+ attributes_for_hash.hash
122
51
  end
123
52
 
124
- class << self
125
- # Used to convert from Strings to BLOBs
126
- def string_to_binary(value)
127
- value
128
- end
129
-
130
- # Used to convert from BLOBs to Strings
131
- def binary_to_string(value)
132
- value
133
- end
134
-
135
- def string_to_date(string)
136
- return string unless string.is_a?(String)
137
- return nil if string.empty?
138
-
139
- fast_string_to_date(string) || fallback_string_to_date(string)
140
- end
141
-
142
- def string_to_time(string)
143
- return string unless string.is_a?(String)
144
- return nil if string.empty?
145
-
146
- fast_string_to_time(string) || fallback_string_to_time(string)
147
- end
53
+ protected
148
54
 
149
- def string_to_dummy_time(string)
150
- return string unless string.is_a?(String)
151
- return nil if string.empty?
152
-
153
- dummy_time_string = "2000-01-01 #{string}"
154
-
155
- fast_string_to_time(dummy_time_string) || begin
156
- time_hash = Date._parse(dummy_time_string)
157
- return nil if time_hash[:hour].nil?
158
- new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
159
- end
160
- end
161
-
162
- # convert something to a boolean
163
- def value_to_boolean(value)
164
- if value.is_a?(String) && value.blank?
165
- nil
166
- else
167
- TRUE_VALUES.include?(value)
168
- end
169
- end
170
-
171
- # Used to convert values to integer.
172
- # handle the case when an integer column is used to store boolean values
173
- def value_to_integer(value)
174
- case value
175
- when TrueClass, FalseClass
176
- value ? 1 : 0
177
- else
178
- value.to_i rescue nil
179
- end
180
- end
181
-
182
- # convert something to a BigDecimal
183
- def value_to_decimal(value)
184
- # Using .class is faster than .is_a? and
185
- # subclasses of BigDecimal will be handled
186
- # in the else clause
187
- if value.class == BigDecimal
188
- value
189
- elsif value.respond_to?(:to_d)
190
- value.to_d
191
- else
192
- value.to_s.to_d
193
- end
194
- end
195
-
196
- protected
197
- # '0.123456' -> 123456
198
- # '1.123456' -> 123456
199
- def microseconds(time)
200
- time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
201
- end
202
-
203
- def new_date(year, mon, mday)
204
- if year && year != 0
205
- Date.new(year, mon, mday) rescue nil
206
- end
207
- end
208
-
209
- def new_time(year, mon, mday, hour, min, sec, microsec)
210
- # Treat 0000-00-00 00:00:00 as nil.
211
- return nil if year.nil? || (year == 0 && mon == 0 && mday == 0)
212
-
213
- Time.time_with_datetime_fallback(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
214
- end
215
-
216
- def fast_string_to_date(string)
217
- if string =~ Format::ISO_DATE
218
- new_date $1.to_i, $2.to_i, $3.to_i
219
- end
220
- end
221
-
222
- if RUBY_VERSION >= '1.9'
223
- # Doesn't handle time zones.
224
- def fast_string_to_time(string)
225
- if string =~ Format::ISO_DATETIME
226
- microsec = ($7.to_r * 1_000_000).to_i
227
- new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
228
- end
229
- end
230
- else
231
- def fast_string_to_time(string)
232
- if string =~ Format::ISO_DATETIME
233
- microsec = ($7.to_f * 1_000_000).round.to_i
234
- new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
235
- end
236
- end
237
- end
238
-
239
- def fallback_string_to_date(string)
240
- new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
241
- end
242
-
243
- def fallback_string_to_time(string)
244
- time_hash = Date._parse(string)
245
- time_hash[:sec_fraction] = microseconds(time_hash)
246
-
247
- new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
248
- end
55
+ def attributes_for_hash
56
+ [self.class, name, default, sql_type_metadata, null, table_name, default_function, collation]
249
57
  end
58
+ end
250
59
 
251
- private
252
- def extract_limit(sql_type)
253
- $1.to_i if sql_type =~ /\((.*)\)/
254
- end
255
-
256
- def extract_precision(sql_type)
257
- $2.to_i if sql_type =~ /^(numeric|decimal|number)\((\d+)(,\d+)?\)/i
258
- end
259
-
260
- def extract_scale(sql_type)
261
- case sql_type
262
- when /^(numeric|decimal|number)\((\d+)\)/i then 0
263
- when /^(numeric|decimal|number)\((\d+)(,(\d+))\)/i then $4.to_i
264
- end
265
- end
266
-
267
- def simplified_type(field_type)
268
- case field_type
269
- when /int/i
270
- :integer
271
- when /float|double/i
272
- :float
273
- when /decimal|numeric|number/i
274
- extract_scale(field_type) == 0 ? :integer : :decimal
275
- when /datetime/i
276
- :datetime
277
- when /timestamp/i
278
- :timestamp
279
- when /time/i
280
- :time
281
- when /date/i
282
- :date
283
- when /clob/i, /text/i
284
- :text
285
- when /blob/i, /binary/i
286
- :binary
287
- when /char/i, /string/i
288
- :string
289
- when /boolean/i
290
- :boolean
291
- end
292
- end
60
+ class NullColumn < Column
61
+ def initialize(name)
62
+ super(name, nil)
63
+ end
293
64
  end
294
65
  end
295
66
  # :startdoc:
@@ -0,0 +1,263 @@
1
+ require 'uri'
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ class ConnectionSpecification #:nodoc:
6
+ attr_reader :name, :config, :adapter_method
7
+
8
+ def initialize(name, config, adapter_method)
9
+ @name, @config, @adapter_method = name, config, adapter_method
10
+ end
11
+
12
+ def initialize_dup(original)
13
+ @config = original.config.dup
14
+ end
15
+
16
+ # Expands a connection string into a hash.
17
+ class ConnectionUrlResolver # :nodoc:
18
+
19
+ # == Example
20
+ #
21
+ # url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
22
+ # ConnectionUrlResolver.new(url).to_hash
23
+ # # => {
24
+ # "adapter" => "postgresql",
25
+ # "host" => "localhost",
26
+ # "port" => 9000,
27
+ # "database" => "foo_test",
28
+ # "username" => "foo",
29
+ # "password" => "bar",
30
+ # "pool" => "5",
31
+ # "timeout" => "3000"
32
+ # }
33
+ def initialize(url)
34
+ raise "Database URL cannot be empty" if url.blank?
35
+ @uri = uri_parser.parse(url)
36
+ @adapter = @uri.scheme && @uri.scheme.tr('-', '_')
37
+ @adapter = "postgresql" if @adapter == "postgres"
38
+
39
+ if @uri.opaque
40
+ @uri.opaque, @query = @uri.opaque.split('?', 2)
41
+ else
42
+ @query = @uri.query
43
+ end
44
+ end
45
+
46
+ # Converts the given URL to a full connection hash.
47
+ def to_hash
48
+ config = raw_config.reject { |_,value| value.blank? }
49
+ config.map { |key,value| config[key] = uri_parser.unescape(value) if value.is_a? String }
50
+ config
51
+ end
52
+
53
+ private
54
+
55
+ def uri
56
+ @uri
57
+ end
58
+
59
+ def uri_parser
60
+ @uri_parser ||= URI::Parser.new
61
+ end
62
+
63
+ # Converts the query parameters of the URI into a hash.
64
+ #
65
+ # "localhost?pool=5&reaping_frequency=2"
66
+ # # => { "pool" => "5", "reaping_frequency" => "2" }
67
+ #
68
+ # returns empty hash if no query present.
69
+ #
70
+ # "localhost"
71
+ # # => {}
72
+ def query_hash
73
+ Hash[(@query || '').split("&").map { |pair| pair.split("=") }]
74
+ end
75
+
76
+ def raw_config
77
+ if uri.opaque
78
+ query_hash.merge({
79
+ "adapter" => @adapter,
80
+ "database" => uri.opaque })
81
+ else
82
+ query_hash.merge({
83
+ "adapter" => @adapter,
84
+ "username" => uri.user,
85
+ "password" => uri.password,
86
+ "port" => uri.port,
87
+ "database" => database_from_path,
88
+ "host" => uri.hostname })
89
+ end
90
+ end
91
+
92
+ # Returns name of the database.
93
+ def database_from_path
94
+ if @adapter == 'sqlite3'
95
+ # 'sqlite3:/foo' is absolute, because that makes sense. The
96
+ # corresponding relative version, 'sqlite3:foo', is handled
97
+ # elsewhere, as an "opaque".
98
+
99
+ uri.path
100
+ else
101
+ # Only SQLite uses a filename as the "database" name; for
102
+ # anything else, a leading slash would be silly.
103
+
104
+ uri.path.sub(%r{^/}, "")
105
+ end
106
+ end
107
+ end
108
+
109
+ ##
110
+ # Builds a ConnectionSpecification from user input.
111
+ class Resolver # :nodoc:
112
+ attr_reader :configurations
113
+
114
+ # Accepts a hash two layers deep, keys on the first layer represent
115
+ # environments such as "production". Keys must be strings.
116
+ def initialize(configurations)
117
+ @configurations = configurations
118
+ end
119
+
120
+ # Returns a hash with database connection information.
121
+ #
122
+ # == Examples
123
+ #
124
+ # Full hash Configuration.
125
+ #
126
+ # configurations = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } }
127
+ # Resolver.new(configurations).resolve(:production)
128
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3"}
129
+ #
130
+ # Initialized with URL configuration strings.
131
+ #
132
+ # configurations = { "production" => "postgresql://localhost/foo" }
133
+ # Resolver.new(configurations).resolve(:production)
134
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
135
+ #
136
+ def resolve(config)
137
+ if config
138
+ resolve_connection config
139
+ elsif env = ActiveRecord::ConnectionHandling::RAILS_ENV.call
140
+ resolve_symbol_connection env.to_sym
141
+ else
142
+ raise AdapterNotSpecified
143
+ end
144
+ end
145
+
146
+ # Expands each key in @configurations hash into fully resolved hash
147
+ def resolve_all
148
+ config = configurations.dup
149
+ config.each do |key, value|
150
+ config[key] = resolve(value) if value
151
+ end
152
+ config
153
+ end
154
+
155
+ # Returns an instance of ConnectionSpecification for a given adapter.
156
+ # Accepts a hash one layer deep that contains all connection information.
157
+ #
158
+ # == Example
159
+ #
160
+ # config = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } }
161
+ # spec = Resolver.new(config).spec(:production)
162
+ # spec.adapter_method
163
+ # # => "sqlite3_connection"
164
+ # spec.config
165
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" }
166
+ #
167
+ def spec(config, name = nil)
168
+ spec = resolve(config).symbolize_keys
169
+
170
+ raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
171
+
172
+ path_to_adapter = "active_record/connection_adapters/#{spec[:adapter]}_adapter"
173
+ begin
174
+ require path_to_adapter
175
+ rescue Gem::LoadError => e
176
+ raise Gem::LoadError, "Specified '#{spec[:adapter]}' for database adapter, but the gem is not loaded. Add `gem '#{e.name}'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord)."
177
+ rescue LoadError => e
178
+ raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile.", e.backtrace
179
+ end
180
+
181
+ adapter_method = "#{spec[:adapter]}_connection"
182
+
183
+ name ||=
184
+ if config.is_a?(Symbol)
185
+ config.to_s
186
+ else
187
+ "primary"
188
+ end
189
+ ConnectionSpecification.new(name, spec, adapter_method)
190
+ end
191
+
192
+ private
193
+
194
+ # Returns fully resolved connection, accepts hash, string or symbol.
195
+ # Always returns a hash.
196
+ #
197
+ # == Examples
198
+ #
199
+ # Symbol representing current environment.
200
+ #
201
+ # Resolver.new("production" => {}).resolve_connection(:production)
202
+ # # => {}
203
+ #
204
+ # One layer deep hash of connection values.
205
+ #
206
+ # Resolver.new({}).resolve_connection("adapter" => "sqlite3")
207
+ # # => { "adapter" => "sqlite3" }
208
+ #
209
+ # Connection URL.
210
+ #
211
+ # Resolver.new({}).resolve_connection("postgresql://localhost/foo")
212
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
213
+ #
214
+ def resolve_connection(spec)
215
+ case spec
216
+ when Symbol
217
+ resolve_symbol_connection spec
218
+ when String
219
+ resolve_url_connection spec
220
+ when Hash
221
+ resolve_hash_connection spec
222
+ end
223
+ end
224
+
225
+ # Takes the environment such as +:production+ or +:development+.
226
+ # This requires that the @configurations was initialized with a key that
227
+ # matches.
228
+ #
229
+ # Resolver.new("production" => {}).resolve_symbol_connection(:production)
230
+ # # => {}
231
+ #
232
+ def resolve_symbol_connection(spec)
233
+ if config = configurations[spec.to_s]
234
+ resolve_connection(config)
235
+ else
236
+ raise(AdapterNotSpecified, "'#{spec}' database is not configured. Available: #{configurations.keys.inspect}")
237
+ end
238
+ end
239
+
240
+ # Accepts a hash. Expands the "url" key that contains a
241
+ # URL database connection to a full connection
242
+ # hash and merges with the rest of the hash.
243
+ # Connection details inside of the "url" key win any merge conflicts
244
+ def resolve_hash_connection(spec)
245
+ if spec["url"] && spec["url"] !~ /^jdbc:/
246
+ connection_hash = resolve_url_connection(spec.delete("url"))
247
+ spec.merge!(connection_hash)
248
+ end
249
+ spec
250
+ end
251
+
252
+ # Takes a connection URL.
253
+ #
254
+ # Resolver.new({}).resolve_url_connection("postgresql://localhost/foo")
255
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
256
+ #
257
+ def resolve_url_connection(url)
258
+ ConnectionUrlResolver.new(url).to_hash
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,22 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module DetermineIfPreparableVisitor
4
+ attr_reader :preparable
5
+
6
+ def accept(*)
7
+ @preparable = true
8
+ super
9
+ end
10
+
11
+ def visit_Arel_Nodes_In(*)
12
+ @preparable = false
13
+ super
14
+ end
15
+
16
+ def visit_Arel_Nodes_SqlLiteral(*)
17
+ @preparable = false
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ class Column < ConnectionAdapters::Column # :nodoc:
5
+ delegate :strict, :extra, to: :sql_type_metadata, allow_nil: true
6
+
7
+ def initialize(*)
8
+ super
9
+ assert_valid_default
10
+ extract_default
11
+ end
12
+
13
+ def has_default?
14
+ return false if blob_or_text_column? # MySQL forbids defaults on blob and text columns
15
+ super
16
+ end
17
+
18
+ def blob_or_text_column?
19
+ /\A(?:tiny|medium|long)?blob\b/ === sql_type || type == :text
20
+ end
21
+
22
+ def unsigned?
23
+ /\bunsigned\z/ === sql_type
24
+ end
25
+
26
+ def case_sensitive?
27
+ collation && collation !~ /_ci\z/
28
+ end
29
+
30
+ def auto_increment?
31
+ extra == 'auto_increment'
32
+ end
33
+
34
+ private
35
+
36
+ def extract_default
37
+ if blob_or_text_column?
38
+ @default = null || strict ? nil : ''
39
+ end
40
+ end
41
+
42
+ def assert_valid_default
43
+ if blob_or_text_column? && default.present?
44
+ raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end