class SQLRunner::Adapters::MySQL

Constants

InvalidPreparedStatement

Public Class Methods

load() click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 8
def self.load
  require "mysql2"
rescue LoadError
  raise MissingDependency, "make sure the `mysql2` gem is available"
end
new(connection_string) click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 14
def initialize(connection_string)
  @connection_string = connection_string
  @uri = URI.parse(@connection_string)
  connect
end

Public Instance Methods

active?() click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 57
def active?
  !@connection&.closed?
rescue Mysql2::Error
  false
end
connect(started = Process.clock_gettime(Process::CLOCK_MONOTONIC)) click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 20
def connect(started = Process.clock_gettime(Process::CLOCK_MONOTONIC))
  @connection = Mysql2::Client.new(
    host: @uri.host,
    port: @uri.port,
    username: @uri.user,
    password: @uri.password,
    database: @uri.path[1..-1]
  )
rescue Mysql2::Error
  ended = Process.clock_gettime(Process::CLOCK_MONOTONIC)

  raise unless ended - started < SQLRunner.timeout

  sleep 0.1
  connect(started)
end
disconnect() click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 37
def disconnect
  @connection&.close && (@connection = nil)
end
execute(query, **bind_vars) click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 46
def execute(query, **bind_vars)
  bound_query, bindings, names = parse(query, bind_vars)
  validate_bindings(query, bind_vars, names)

  statement = @connection.prepare(bound_query)
  statement.execute(*bindings, cast: true)
rescue Mysql2::Error
  reconnect
  execute(query, **bind_vars)
end
inspect() click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 67
def inspect
  to_s
end
parse(query, bind_vars) click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 71
def parse(query, bind_vars)
  bindings = []
  names = []

  parsed_query = query.gsub(/(:?):([a-zA-Z]\w*)/) do |match|
    next match if Regexp.last_match(1) == ":" # skip type casting

    name = match[1..-1]
    sym_name = name.to_sym
    names << sym_name
    bindings << bind_vars[sym_name]

    "?"
  end

  [parsed_query, bindings, names]
end
reconnect() click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 41
def reconnect
  disconnect
  connect
end
to_s() click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 63
def to_s
  %[#<#{self.class.name} #{format('0x00%x', (object_id << 1))}>]
end

Private Instance Methods

validate_bindings(query, bind_vars, names) click to toggle source
# File lib/sql_runner/adapters/mysql.rb, line 89
        def validate_bindings(query, bind_vars, names)
  names.each do |name|
    next if bind_vars.key?(name)

    raise InvalidPreparedStatement,
          "missing value for :#{name} in #{query}"
  end
end