Class: StrongMigrations::Adapters::MySQLAdapter

Inherits:
AbstractAdapter show all
Defined in:
lib/strong_migrations/adapters/mysql_adapter.rb

Direct Known Subclasses

MariaDBAdapter

Instance Method Summary collapse

Methods inherited from AbstractAdapter

#initialize

Constructor Details

This class inherits a constructor from StrongMigrations::Adapters::AbstractAdapter

Instance Method Details

#add_column_default_safe?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 46

def add_column_default_safe?
  server_version >= Gem::Version.new("8.0.12")
end

#analyze_table(table) ⇒ Object



42
43
44
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 42

def analyze_table(table)
  connection.execute "ANALYZE TABLE #{connection.quote_table_name(table.to_s)}"
end

#change_type_safe?(table, column, type, options, existing_column, existing_type) ⇒ Boolean

Returns:

  • (Boolean)


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 50

def change_type_safe?(table, column, type, options, existing_column, existing_type)
  safe = false

  case type.to_s
  when "string"
    limit = options[:limit] || 255
    if ["varchar"].include?(existing_type) && limit >= existing_column.limit
      # https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html
      # https://mariadb.com/kb/en/innodb-online-ddl-operations-with-the-instant-alter-algorithm/#changing-the-data-type-of-a-column
      # increased limit, but doesn't change number of length bytes
      # 1-255 = 1 byte, 256-65532 = 2 bytes, 65533+ = too big for varchar

      # account for charset
      # https://dev.mysql.com/doc/refman/8.0/en/charset-mysql.html
      # https://mariadb.com/kb/en/supported-character-sets-and-collations/
      sql = <<~SQL
        SELECT cs.MAXLEN
        FROM INFORMATION_SCHEMA.CHARACTER_SETS cs
        INNER JOIN INFORMATION_SCHEMA.COLLATIONS c ON c.CHARACTER_SET_NAME = cs.CHARACTER_SET_NAME
        INNER JOIN INFORMATION_SCHEMA.TABLES t ON t.TABLE_COLLATION = c.COLLATION_NAME
        WHERE t.TABLE_SCHEMA = database() AND t.TABLE_NAME = #{connection.quote(table)}
      SQL
      row = connection.select_all(sql).first
      if row
        threshold = 255 / row["MAXLEN"]
        safe = limit <= threshold || existing_column.limit > threshold
      else
        warn "[strong_migrations] Could not determine charset"
      end
    end
  end

  safe
end

#check_lock_timeout(limit) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 34

def check_lock_timeout(limit)
  lock_timeout = connection.select_all("SHOW VARIABLES LIKE 'lock_wait_timeout'").first["Value"]
  # lock timeout is an integer
  if lock_timeout.to_i > limit
    warn "[strong_migrations] DANGER: Lock timeout is longer than #{limit} seconds: #{lock_timeout}"
  end
end

#min_versionObject



10
11
12
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 10

def min_version
  "5.7"
end

#nameObject



6
7
8
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 6

def name
  "MySQL"
end

#rewrite_blocksObject



90
91
92
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 90

def rewrite_blocks
  "writes"
end

#server_versionObject



14
15
16
17
18
19
20
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 14

def server_version
  @server_version ||= begin
    target_version(StrongMigrations.target_mysql_version) do
      select_all("SELECT VERSION()").first["VERSION()"].split("-").first
    end
  end
end

#set_lock_timeout(timeout) ⇒ Object



27
28
29
30
31
32
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 27

def set_lock_timeout(timeout)
  # fix deprecation warning with Active Record 7.1
  timeout = timeout.value if timeout.is_a?(ActiveSupport::Duration)

  select_all("SET lock_wait_timeout = #{connection.quote(timeout)}")
end

#set_statement_timeout(timeout) ⇒ Object



22
23
24
25
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 22

def set_statement_timeout(timeout)
  # use ceil to prevent no timeout for values under 1 ms
  select_all("SET max_execution_time = #{connection.quote((timeout.to_f * 1000).ceil)}")
end

#strict_mode?Boolean

Returns:

  • (Boolean)


85
86
87
88
# File 'lib/strong_migrations/adapters/mysql_adapter.rb', line 85

def strict_mode?
  sql_modes = sql_modes()
  sql_modes.include?("STRICT_ALL_TABLES") || sql_modes.include?("STRICT_TRANS_TABLES")
end