Class: SQLRunner::Adapters::MySQL

Inherits:
Object
  • Object
show all
Defined in:
lib/sql_runner/adapters/mysql.rb

Direct Known Subclasses

ActiveRecord::MySQL

Constant Summary collapse

InvalidPreparedStatement =
Class.new(StandardError)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection_string) ⇒ MySQL

Returns a new instance of MySQL.



20
21
22
23
24
# File 'lib/sql_runner/adapters/mysql.rb', line 20

def initialize(connection_string)
  @connection_string = connection_string
  @uri = URI.parse(@connection_string)
  connect
end

Class Method Details

.create_connection_pool(timeout:, size:, connection_string:) ⇒ Object



14
15
16
17
18
# File 'lib/sql_runner/adapters/mysql.rb', line 14

def self.create_connection_pool(timeout:, size:, connection_string:)
  ConnectionPool.new(timeout:, size:) do
    new(connection_string)
  end
end

.loadObject



8
9
10
11
12
# 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

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


65
66
67
68
69
# File 'lib/sql_runner/adapters/mysql.rb', line 65

def active?
  !@connection&.closed?
rescue Mysql2::Error
  false
end

#connect(started = Process.clock_gettime(Process::CLOCK_MONOTONIC)) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/sql_runner/adapters/mysql.rb', line 26

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

#disconnectObject



43
44
45
# File 'lib/sql_runner/adapters/mysql.rb', line 43

def disconnect
  @connection&.close && (@connection = nil)
end

#execute(query, **bind_vars) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/sql_runner/adapters/mysql.rb', line 52

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,
    as: :hash,
    cast_booleans: true
  )
end

#inspectObject



75
76
77
# File 'lib/sql_runner/adapters/mysql.rb', line 75

def inspect
  to_s
end

#parse(query, bind_vars) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/sql_runner/adapters/mysql.rb', line 79

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

#reconnectObject



47
48
49
50
# File 'lib/sql_runner/adapters/mysql.rb', line 47

def reconnect
  disconnect
  connect
end

#to_sObject



71
72
73
# File 'lib/sql_runner/adapters/mysql.rb', line 71

def to_s
  %[#<#{self.class.name} #{format('0x00%x', (object_id << 1))}>]
end