activerecord 4.2.0 → 4.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -1
  3. data/lib/active_record.rb +3 -0
  4. data/lib/active_record/aggregations.rb +6 -3
  5. data/lib/active_record/association_relation.rb +13 -0
  6. data/lib/active_record/associations.rb +5 -4
  7. data/lib/active_record/associations/association.rb +15 -3
  8. data/lib/active_record/associations/association_scope.rb +1 -0
  9. data/lib/active_record/associations/belongs_to_association.rb +13 -5
  10. data/lib/active_record/associations/builder/association.rb +1 -1
  11. data/lib/active_record/associations/builder/collection_association.rb +5 -1
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +8 -4
  13. data/lib/active_record/associations/collection_association.rb +35 -15
  14. data/lib/active_record/associations/collection_proxy.rb +15 -9
  15. data/lib/active_record/associations/foreign_association.rb +11 -0
  16. data/lib/active_record/associations/has_many_association.rb +30 -15
  17. data/lib/active_record/associations/has_many_through_association.rb +11 -2
  18. data/lib/active_record/associations/has_one_association.rb +1 -0
  19. data/lib/active_record/associations/join_dependency.rb +8 -2
  20. data/lib/active_record/associations/join_dependency/join_association.rb +7 -1
  21. data/lib/active_record/associations/preloader.rb +4 -4
  22. data/lib/active_record/associations/preloader/association.rb +5 -1
  23. data/lib/active_record/associations/singular_association.rb +2 -8
  24. data/lib/active_record/associations/through_association.rb +11 -6
  25. data/lib/active_record/attribute.rb +15 -1
  26. data/lib/active_record/attribute_assignment.rb +2 -2
  27. data/lib/active_record/attribute_methods.rb +4 -8
  28. data/lib/active_record/attribute_methods/before_type_cast.rb +5 -0
  29. data/lib/active_record/attribute_methods/dirty.rb +14 -4
  30. data/lib/active_record/attribute_methods/time_zone_conversion.rb +5 -1
  31. data/lib/active_record/attribute_methods/write.rb +1 -1
  32. data/lib/active_record/attribute_set.rb +4 -0
  33. data/lib/active_record/attribute_set/builder.rb +32 -12
  34. data/lib/active_record/attributes.rb +8 -0
  35. data/lib/active_record/autosave_association.rb +24 -9
  36. data/lib/active_record/base.rb +4 -5
  37. data/lib/active_record/callbacks.rb +1 -1
  38. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +12 -6
  39. data/lib/active_record/connection_adapters/abstract/database_statements.rb +23 -3
  40. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -0
  42. data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
  43. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +26 -16
  44. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +87 -24
  45. data/lib/active_record/connection_adapters/abstract/transaction.rb +2 -6
  46. data/lib/active_record/connection_adapters/abstract_adapter.rb +25 -7
  47. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +73 -10
  48. data/lib/active_record/connection_adapters/column.rb +2 -2
  49. data/lib/active_record/connection_adapters/mysql2_adapter.rb +7 -21
  50. data/lib/active_record/connection_adapters/mysql_adapter.rb +10 -3
  51. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
  52. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -1
  53. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -0
  54. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -0
  55. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
  56. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -1
  57. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -0
  58. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
  59. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +3 -3
  60. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +21 -13
  61. data/lib/active_record/connection_adapters/postgresql_adapter.rb +12 -12
  62. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -28
  63. data/lib/active_record/connection_handling.rb +1 -1
  64. data/lib/active_record/core.rb +28 -15
  65. data/lib/active_record/counter_cache.rb +1 -1
  66. data/lib/active_record/enum.rb +2 -3
  67. data/lib/active_record/errors.rb +6 -5
  68. data/lib/active_record/explain_subscriber.rb +1 -1
  69. data/lib/active_record/fixtures.rb +9 -7
  70. data/lib/active_record/gem_version.rb +1 -1
  71. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  72. data/lib/active_record/locking/optimistic.rb +16 -14
  73. data/lib/active_record/migration.rb +38 -10
  74. data/lib/active_record/model_schema.rb +4 -2
  75. data/lib/active_record/nested_attributes.rb +13 -3
  76. data/lib/active_record/no_touching.rb +1 -1
  77. data/lib/active_record/persistence.rb +7 -4
  78. data/lib/active_record/railtie.rb +5 -3
  79. data/lib/active_record/railties/databases.rake +17 -24
  80. data/lib/active_record/reflection.rb +40 -28
  81. data/lib/active_record/relation.rb +3 -2
  82. data/lib/active_record/relation/calculations.rb +10 -3
  83. data/lib/active_record/relation/delegation.rb +1 -1
  84. data/lib/active_record/relation/finder_methods.rb +4 -16
  85. data/lib/active_record/relation/merger.rb +24 -1
  86. data/lib/active_record/relation/predicate_builder.rb +32 -3
  87. data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -2
  88. data/lib/active_record/relation/query_methods.rb +29 -27
  89. data/lib/active_record/relation/spawn_methods.rb +7 -3
  90. data/lib/active_record/schema_dumper.rb +1 -1
  91. data/lib/active_record/schema_migration.rb +1 -4
  92. data/lib/active_record/scoping/default.rb +1 -0
  93. data/lib/active_record/tasks/database_tasks.rb +5 -2
  94. data/lib/active_record/tasks/mysql_database_tasks.rb +30 -16
  95. data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -8
  96. data/lib/active_record/transactions.rb +21 -11
  97. data/lib/active_record/type/boolean.rb +1 -0
  98. data/lib/active_record/type/date.rb +4 -0
  99. data/lib/active_record/type/date_time.rb +14 -3
  100. data/lib/active_record/type/decimal.rb +27 -3
  101. data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
  102. data/lib/active_record/type/integer.rb +9 -5
  103. data/lib/active_record/type/numeric.rb +1 -1
  104. data/lib/active_record/type/serialized.rb +7 -1
  105. data/lib/active_record/type/string.rb +4 -0
  106. data/lib/active_record/type/value.rb +9 -0
  107. data/lib/active_record/validations/uniqueness.rb +16 -6
  108. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -3
  109. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -6
  110. metadata +9 -7
@@ -55,11 +55,7 @@ module ActiveRecord
55
55
  end
56
56
 
57
57
  def add_record(record)
58
- if record.has_transactional_callbacks?
59
- records << record
60
- else
61
- record.set_transaction_state(@state)
62
- end
58
+ records << record
63
59
  end
64
60
 
65
61
  def rollback
@@ -192,7 +188,7 @@ module ActiveRecord
192
188
  ensure
193
189
  unless error
194
190
  if Thread.current.status == 'aborting'
195
- rollback_transaction
191
+ rollback_transaction if transaction
196
192
  else
197
193
  begin
198
194
  commit_transaction
@@ -111,6 +111,18 @@ module ActiveRecord
111
111
  @prepared_statements = false
112
112
  end
113
113
 
114
+ class Version
115
+ include Comparable
116
+
117
+ def initialize(version_string)
118
+ @version = version_string.split('.').map(&:to_i)
119
+ end
120
+
121
+ def <=>(version_string)
122
+ @version <=> version_string.split('.').map(&:to_i)
123
+ end
124
+ end
125
+
114
126
  class BindCollector < Arel::Collectors::Bind
115
127
  def compile(bvs, conn)
116
128
  super(bvs.map { |bv| conn.quote(*bv.reverse) })
@@ -341,9 +353,6 @@ module ActiveRecord
341
353
  def create_savepoint(name = nil)
342
354
  end
343
355
 
344
- def rollback_to_savepoint(name = nil)
345
- end
346
-
347
356
  def release_savepoint(name = nil)
348
357
  end
349
358
 
@@ -385,7 +394,7 @@ module ActiveRecord
385
394
  end
386
395
 
387
396
  def column_name_for_operation(operation, node) # :nodoc:
388
- node.to_sql
397
+ visitor.accept(node, collector).value
389
398
  end
390
399
 
391
400
  protected
@@ -445,12 +454,21 @@ module ActiveRecord
445
454
  end
446
455
 
447
456
  def extract_limit(sql_type) # :nodoc:
448
- $1.to_i if sql_type =~ /\((.*)\)/
457
+ case sql_type
458
+ when /^bigint/i
459
+ 8
460
+ when /\((.*)\)/
461
+ $1.to_i
462
+ end
449
463
  end
450
464
 
451
465
  def translate_exception_class(e, sql)
452
- message = "#{e.class.name}: #{e.message}: #{sql}"
453
- @logger.error message if @logger
466
+ begin
467
+ message = "#{e.class.name}: #{e.message}: #{sql}"
468
+ rescue Encoding::CompatibilityError
469
+ message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
470
+ end
471
+
454
472
  exception = translate_exception(e, message)
455
473
  exception.set_backtrace e.backtrace
456
474
  exception
@@ -58,6 +58,12 @@ module ActiveRecord
58
58
  SchemaCreation.new self
59
59
  end
60
60
 
61
+ def prepare_column_options(column, types) # :nodoc:
62
+ spec = super
63
+ spec.delete(:limit) if :boolean === column.type
64
+ spec
65
+ end
66
+
61
67
  class Column < ConnectionAdapters::Column # :nodoc:
62
68
  attr_reader :collation, :strict, :extra
63
69
 
@@ -197,7 +203,7 @@ module ActiveRecord
197
203
  #
198
204
  # http://bugs.mysql.com/bug.php?id=39170
199
205
  def supports_transaction_isolation?
200
- version[0] >= 5
206
+ version >= '5.0.0'
201
207
  end
202
208
 
203
209
  def supports_indexes_in_create?
@@ -209,7 +215,11 @@ module ActiveRecord
209
215
  end
210
216
 
211
217
  def supports_views?
212
- version[0] >= 5
218
+ version >= '5.0.0'
219
+ end
220
+
221
+ def supports_datetime_with_precision?
222
+ version >= '5.6.4'
213
223
  end
214
224
 
215
225
  def native_database_types
@@ -272,6 +282,14 @@ module ActiveRecord
272
282
  0
273
283
  end
274
284
 
285
+ def quoted_date(value)
286
+ if supports_datetime_with_precision? && value.acts_like?(:time) && value.respond_to?(:usec)
287
+ "#{super}.#{sprintf("%06d", value.usec)}"
288
+ else
289
+ super
290
+ end
291
+ end
292
+
275
293
  # REFERENTIAL INTEGRITY ====================================
276
294
 
277
295
  def disable_referential_integrity #:nodoc:
@@ -324,7 +342,7 @@ module ActiveRecord
324
342
  execute "COMMIT"
325
343
  end
326
344
 
327
- def rollback_db_transaction #:nodoc:
345
+ def exec_rollback_db_transaction #:nodoc:
328
346
  execute "ROLLBACK"
329
347
  end
330
348
 
@@ -401,6 +419,7 @@ module ActiveRecord
401
419
  result.collect { |field| field.first }
402
420
  end
403
421
  end
422
+ alias data_sources tables
404
423
 
405
424
  def truncate(table_name, name = nil)
406
425
  execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
@@ -420,6 +439,7 @@ module ActiveRecord
420
439
 
421
440
  tables(nil, schema, table).any?
422
441
  end
442
+ alias data_source_exists? table_exists?
423
443
 
424
444
  # Returns an array of indexes for the given table.
425
445
  def indexes(table_name, name = nil) #:nodoc:
@@ -492,6 +512,8 @@ module ActiveRecord
492
512
 
493
513
  def rename_index(table_name, old_name, new_name)
494
514
  if supports_rename_index?
515
+ validate_index_length!(table_name, new_name)
516
+
495
517
  execute "ALTER TABLE #{quote_table_name(table_name)} RENAME INDEX #{quote_table_name(old_name)} TO #{quote_table_name(new_name)}"
496
518
  else
497
519
  super
@@ -582,6 +604,13 @@ module ActiveRecord
582
604
  when 0x1000000..0xffffffff; 'longtext'
583
605
  else raise(ActiveRecordError, "No text type has character length #{limit}")
584
606
  end
607
+ when 'datetime'
608
+ return super unless precision
609
+
610
+ case precision
611
+ when 0..6; "datetime(#{precision})"
612
+ else raise(ActiveRecordError, "No datetime type has precision of #{precision}. The allowed range of precision is from 0 to 6.")
613
+ end
585
614
  else
586
615
  super
587
616
  end
@@ -589,8 +618,10 @@ module ActiveRecord
589
618
 
590
619
  # SHOW VARIABLES LIKE 'name'
591
620
  def show_variable(name)
592
- variables = select_all("SHOW VARIABLES LIKE '#{name}'", 'SCHEMA')
621
+ variables = select_all("select @@#{name} as 'Value'", 'SCHEMA')
593
622
  variables.first['Value'] unless variables.empty?
623
+ rescue ActiveRecord::StatementInvalid
624
+ nil
594
625
  end
595
626
 
596
627
  # Returns a table's primary key and belonging sequence.
@@ -633,6 +664,21 @@ module ActiveRecord
633
664
  end
634
665
  end
635
666
 
667
+ # In MySQL 5.7.5 and up, ONLY_FULL_GROUP_BY affects handling of queries that use
668
+ # DISTINCT and ORDER BY. It requires the ORDER BY columns in the select list for
669
+ # distinct queries, and requires that the ORDER BY include the distinct column.
670
+ # See https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
671
+ def columns_for_distinct(columns, orders) # :nodoc:
672
+ order_columns = orders.reject(&:blank?).map { |s|
673
+ # Convert Arel node to string
674
+ s = s.to_sql unless s.is_a?(String)
675
+ # Remove any ASC/DESC modifiers
676
+ s.gsub(/\s+(?:ASC|DESC)\b/i, '')
677
+ }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
678
+
679
+ [super, *order_columns].join(', ')
680
+ end
681
+
636
682
  def strict_mode?
637
683
  self.class.type_cast_config_to_boolean(@config.fetch(:strict, true))
638
684
  end
@@ -670,6 +716,11 @@ module ActiveRecord
670
716
  m.alias_type %r(year)i, 'integer'
671
717
  m.alias_type %r(bit)i, 'binary'
672
718
 
719
+ m.register_type(%r(datetime)i) do |sql_type|
720
+ precision = extract_precision(sql_type)
721
+ MysqlDateTime.new(precision: precision)
722
+ end
723
+
673
724
  m.register_type(%r(enum)i) do |sql_type|
674
725
  limit = sql_type[/^enum\((.+)\)/i, 1]
675
726
  .split(',').map{|enum| enum.strip.length - 2}.max
@@ -693,6 +744,10 @@ module ActiveRecord
693
744
  subsubselect = select.clone
694
745
  subsubselect.projections = [key]
695
746
 
747
+ # Materialize subquery by adding distinct
748
+ # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
749
+ subsubselect.distinct unless select.limit || select.offset || select.orders.any?
750
+
696
751
  subselect = Arel::SelectManager.new(select.engine)
697
752
  subselect.project Arel.sql(key.name)
698
753
  subselect.from subsubselect.as('__active_record_temp')
@@ -703,7 +758,7 @@ module ActiveRecord
703
758
  case length
704
759
  when Hash
705
760
  column_names.each {|name| option_strings[name] += "(#{length[name]})" if length.has_key?(name) && length[name].present?}
706
- when Fixnum
761
+ when Integer
707
762
  column_names.each {|name| option_strings[name] += "(#{length})"}
708
763
  end
709
764
  end
@@ -797,7 +852,7 @@ module ActiveRecord
797
852
  private
798
853
 
799
854
  def version
800
- @version ||= full_version.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
855
+ @version ||= Version.new(full_version.match(/^\d+\.\d+\.\d+/)[0])
801
856
  end
802
857
 
803
858
  def mariadb?
@@ -805,7 +860,7 @@ module ActiveRecord
805
860
  end
806
861
 
807
862
  def supports_rename_index?
808
- mariadb? ? false : (version[0] == 5 && version[1] >= 7) || version[0] >= 6
863
+ mariadb? ? false : version >= '5.7.6'
809
864
  end
810
865
 
811
866
  def configure_connection
@@ -816,9 +871,9 @@ module ActiveRecord
816
871
  variables['sql_auto_is_null'] = 0
817
872
 
818
873
  # Increase timeout so the server doesn't disconnect us.
819
- wait_timeout = @config[:wait_timeout]
820
- wait_timeout = 2147483 unless wait_timeout.is_a?(Fixnum)
821
- variables['wait_timeout'] = self.class.type_cast_config_to_integer(wait_timeout)
874
+ wait_timeout = self.class.type_cast_config_to_integer(@config[:wait_timeout])
875
+ wait_timeout = 2147483 unless wait_timeout.is_a?(Integer)
876
+ variables["wait_timeout"] = wait_timeout
822
877
 
823
878
  # Make MySQL reject illegal values rather than truncating or blanking them, see
824
879
  # http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_strict_all_tables
@@ -859,6 +914,14 @@ module ActiveRecord
859
914
  end
860
915
  end
861
916
 
917
+ class MysqlDateTime < Type::DateTime # :nodoc:
918
+ private
919
+
920
+ def has_precision?
921
+ precision || 0
922
+ end
923
+ end
924
+
862
925
  class MysqlString < Type::String # :nodoc:
863
926
  def type_cast_for_database(value)
864
927
  case value
@@ -16,7 +16,7 @@ module ActiveRecord
16
16
  attr_reader :name, :cast_type, :null, :sql_type, :default, :default_function
17
17
 
18
18
  delegate :type, :precision, :scale, :limit, :klass, :accessor,
19
- :number?, :binary?, :changed?,
19
+ :text?, :number?, :binary?, :changed?,
20
20
  :type_cast_from_user, :type_cast_from_database, :type_cast_for_database,
21
21
  :type_cast_for_schema,
22
22
  to: :cast_type
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  # It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
32
32
  # +null+ determines if this column allows +NULL+ values.
33
33
  def initialize(name, default, cast_type, sql_type = nil, null = true)
34
- @name = name
34
+ @name = name.freeze
35
35
  @cast_type = cast_type
36
36
  @sql_type = sql_type
37
37
  @null = null
@@ -1,6 +1,6 @@
1
1
  require 'active_record/connection_adapters/abstract_mysql_adapter'
2
2
 
3
- gem 'mysql2', '~> 0.3.13'
3
+ gem 'mysql2', '>= 0.3.13', '< 0.6.0'
4
4
  require 'mysql2'
5
5
 
6
6
  module ActiveRecord
@@ -39,7 +39,7 @@ module ActiveRecord
39
39
 
40
40
  MAX_INDEX_LENGTH_FOR_UTF8MB4 = 191
41
41
  def initialize_schema_migrations_table
42
- if @config[:encoding] == 'utf8mb4'
42
+ if charset == 'utf8mb4'
43
43
  ActiveRecord::SchemaMigration.create_table(MAX_INDEX_LENGTH_FOR_UTF8MB4)
44
44
  else
45
45
  ActiveRecord::SchemaMigration.create_table
@@ -74,20 +74,11 @@ module ActiveRecord
74
74
  @connection.escape(string)
75
75
  end
76
76
 
77
- def quoted_date(value)
78
- if value.acts_like?(:time) && value.respond_to?(:usec)
79
- "#{super}.#{sprintf("%06d", value.usec)}"
80
- else
81
- super
82
- end
83
- end
84
-
85
77
  #--
86
78
  # CONNECTION MANAGEMENT ====================================
87
79
  #++
88
80
 
89
81
  def active?
90
- return false unless @connection
91
82
  @connection.ping
92
83
  end
93
84
 
@@ -102,10 +93,7 @@ module ActiveRecord
102
93
  # Otherwise, this method does nothing.
103
94
  def disconnect!
104
95
  super
105
- unless @connection.nil?
106
- @connection.close
107
- @connection = nil
108
- end
96
+ @connection.close
109
97
  end
110
98
 
111
99
  #--
@@ -222,11 +210,9 @@ module ActiveRecord
222
210
 
223
211
  # Executes the SQL statement in the context of this connection.
224
212
  def execute(sql, name = nil)
225
- if @connection
226
- # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
227
- # made since we established the connection
228
- @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
229
- end
213
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
214
+ # made since we established the connection
215
+ @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
230
216
 
231
217
  super
232
218
  end
@@ -271,7 +257,7 @@ module ActiveRecord
271
257
  end
272
258
 
273
259
  def full_version
274
- @full_version ||= @connection.info[:version]
260
+ @full_version ||= @connection.server_info[:version]
275
261
  end
276
262
 
277
263
  def set_field_encoding field_name
@@ -57,7 +57,7 @@ module ActiveRecord
57
57
  # * <tt>:database</tt> - The name of the database. No default, must be provided.
58
58
  # * <tt>:encoding</tt> - (Optional) Sets the client encoding by executing "SET NAMES <encoding>" after connection.
59
59
  # * <tt>:reconnect</tt> - Defaults to false (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html).
60
- # * <tt>:strict</tt> - Defaults to true. Enable STRICT_ALL_TABLES. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html)
60
+ # * <tt>:strict</tt> - Defaults to true. Enable STRICT_ALL_TABLES. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/sql-mode.html)
61
61
  # * <tt>:variables</tt> - (Optional) A hash session variables to send as <tt>SET @@SESSION.key = value</tt> on each database connection. Use the value +:default+ to set a variable to its DEFAULT value. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/set-statement.html).
62
62
  # * <tt>:sslca</tt> - Necessary to use MySQL with an SSL connection.
63
63
  # * <tt>:sslkey</tt> - Necessary to use MySQL with an SSL connection.
@@ -245,7 +245,7 @@ module ActiveRecord
245
245
  return @client_encoding if @client_encoding
246
246
 
247
247
  result = exec_query(
248
- "SHOW VARIABLES WHERE Variable_name = 'character_set_client'",
248
+ "select @@character_set_client",
249
249
  'SCHEMA')
250
250
  @client_encoding = ENCODINGS[result.rows.last.last]
251
251
  end
@@ -282,6 +282,10 @@ module ActiveRecord
282
282
  super
283
283
  end
284
284
  end
285
+
286
+ def has_precision?
287
+ precision || 0
288
+ end
285
289
  end
286
290
 
287
291
  class Time < Type::Time # :nodoc:
@@ -328,8 +332,11 @@ module ActiveRecord
328
332
 
329
333
  def initialize_type_map(m) # :nodoc:
330
334
  super
331
- m.register_type %r(datetime)i, Fields::DateTime.new
332
335
  m.register_type %r(time)i, Fields::Time.new
336
+ m.register_type(%r(datetime)i) do |sql_type|
337
+ precision = extract_precision(sql_type)
338
+ Fields::DateTime.new(precision: precision)
339
+ end
333
340
  end
334
341
 
335
342
  def exec_without_stmt(sql, name = 'SQL') # :nodoc:
@@ -223,7 +223,7 @@ module ActiveRecord
223
223
  end
224
224
 
225
225
  # Aborts a transaction.
226
- def rollback_db_transaction
226
+ def exec_rollback_db_transaction
227
227
  execute "ROLLBACK"
228
228
  end
229
229
  end
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  end
19
19
 
20
20
  attr_reader :subtype, :delimiter
21
- delegate :type, to: :subtype
21
+ delegate :type, :limit, to: :subtype
22
22
 
23
23
  def initialize(subtype, delimiter = ',')
24
24
  @subtype = subtype
@@ -80,6 +80,7 @@ module ActiveRecord
80
80
  value
81
81
  end
82
82
  when nil then "NULL"
83
+ when ::Date, ::DateTime, ::Time then subtype.type_cast_for_schema(value)
83
84
  else value
84
85
  end
85
86
  end
@@ -5,6 +5,7 @@ module ActiveRecord
5
5
  class Bytea < Type::Binary # :nodoc:
6
6
  def type_cast_from_database(value)
7
7
  return if value.nil?
8
+ return value.to_s if value.is_a?(Type::Binary::Data)
8
9
  PGconn.unescape_bytea(super)
9
10
  end
10
11
  end