Skip to content

Commit fe11cac

Browse files
committed
[mysql] type-map support copy-pasta from AR 4.2 (closer to full compatibility)
fixes boolean type columns #626 and probably some type related issues as well
1 parent 67f7d6f commit fe11cac

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

lib/arjdbc/mysql/adapter.rb

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,8 +678,79 @@ def empty_insert_statement_value
678678
"VALUES ()"
679679
end
680680

681+
# @note since AR 4.2
682+
def valid_type?(type)
683+
! native_database_types[type].nil?
684+
end
685+
686+
# @private
687+
Type = ActiveRecord::Type if AR42
688+
681689
protected
682690

691+
# @private
692+
def initialize_type_map(m)
693+
super
694+
695+
register_class_with_limit m, %r(char)i, MysqlString
696+
697+
m.register_type %r(tinytext)i, Type::Text.new(limit: 2**8 - 1)
698+
m.register_type %r(tinyblob)i, Type::Binary.new(limit: 2**8 - 1)
699+
m.register_type %r(text)i, Type::Text.new(limit: 2**16 - 1)
700+
m.register_type %r(blob)i, Type::Binary.new(limit: 2**16 - 1)
701+
m.register_type %r(mediumtext)i, Type::Text.new(limit: 2**24 - 1)
702+
m.register_type %r(mediumblob)i, Type::Binary.new(limit: 2**24 - 1)
703+
m.register_type %r(longtext)i, Type::Text.new(limit: 2**32 - 1)
704+
m.register_type %r(longblob)i, Type::Binary.new(limit: 2**32 - 1)
705+
m.register_type %r(^float)i, Type::Float.new(limit: 24)
706+
m.register_type %r(^double)i, Type::Float.new(limit: 53)
707+
708+
register_integer_type m, %r(^bigint)i, limit: 8
709+
register_integer_type m, %r(^int)i, limit: 4
710+
register_integer_type m, %r(^mediumint)i, limit: 3
711+
register_integer_type m, %r(^smallint)i, limit: 2
712+
register_integer_type m, %r(^tinyint)i, limit: 1
713+
714+
m.alias_type %r(tinyint\(1\))i, 'boolean' if emulate_booleans
715+
m.alias_type %r(set)i, 'varchar'
716+
m.alias_type %r(year)i, 'integer'
717+
m.alias_type %r(bit)i, 'binary'
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+
724+
m.register_type(%r(enum)i) do |sql_type|
725+
limit = sql_type[/^enum\((.+)\)/i, 1]
726+
.split(',').map{|enum| enum.strip.length - 2}.max
727+
MysqlString.new(limit: limit)
728+
end
729+
end if AR42
730+
731+
# @private
732+
def register_integer_type(mapping, key, options)
733+
mapping.register_type(key) do |sql_type|
734+
if /unsigned/i =~ sql_type
735+
Type::UnsignedInteger.new(options)
736+
else
737+
Type::Integer.new(options)
738+
end
739+
end
740+
end if AR42
741+
742+
# MySQL is too stupid to create a temporary table for use subquery, so we have
743+
# to give it some prompting in the form of a subsubquery. Ugh!
744+
# @note since AR 4.2
745+
def subquery_for(key, select)
746+
subsubselect = select.clone
747+
subsubselect.projections = [key]
748+
749+
subselect = Arel::SelectManager.new(select.engine)
750+
subselect.project Arel.sql(key.name)
751+
subselect.from subsubselect.as('__active_record_temp')
752+
end if AR42
753+
683754
def quoted_columns_for_index(column_names, options = {})
684755
length = options[:length] if options.is_a?(Hash)
685756

@@ -744,6 +815,39 @@ def full_version
744815
end
745816
end
746817

818+
# @private
819+
def emulate_booleans; ::ArJdbc::MySQL.emulate_booleans?; end # due AR 4.2
820+
821+
# @private
822+
class MysqlDateTime < Type::DateTime
823+
private
824+
825+
def has_precision?
826+
precision || 0
827+
end
828+
end if AR42
829+
830+
# @private
831+
class MysqlString < Type::String
832+
def type_cast_for_database(value)
833+
case value
834+
when true then "1"
835+
when false then "0"
836+
else super
837+
end
838+
end
839+
840+
private
841+
842+
def cast_value(value)
843+
case value
844+
when true then "1"
845+
when false then "0"
846+
else super
847+
end
848+
end
849+
end if AR42
850+
747851
end
748852
end
749853

0 commit comments

Comments
 (0)