Module: Simple::SQL::ConnectionAdapter

Included in:
Simple::SQL::Connection::ActiveRecordConnection, Simple::SQL::Connection::PgConnection
Defined in:
lib/simple/sql/connection_adapter.rb

Overview

This module implements an adapter between the Simple::SQL interface (i.e. ask, all, first, transaction) and a raw connection.

This module can be mixed onto objects that implement a raw_connection method, which must return a Pg::Connection.

Constant Summary collapse

Logging =
::Simple::SQL::Logging
Encoder =
::Simple::SQL::Encoder
Decoder =
::Simple::SQL::Decoder
Scope =
::Simple::SQL::Scope

Instance Method Summary collapse

Instance Method Details

#add_page_info(scope, results) ⇒ Object

Raises:

  • (ArgumentError)


63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/simple/sql/connection_adapter.rb', line 63

def add_page_info(scope, results)
  raise ArgumentError, "expect Array but get a #{results.class.name}" unless results.is_a?(Array)
  raise ArgumentError, "per must be > 0" unless scope.per > 0

  # optimization: add empty case (page <= 1 && results.empty?)
  if scope.page <= 1 && results.empty?
    Scope::PageInfo.attach(results, total_count: 0, per: scope.per, page: scope.page)
  else
    sql = "SELECT COUNT(*) FROM (#{scope.to_sql(pagination: false)}) simple_sql_count"
    total_count = ask(sql, *scope.args)
    Scope::PageInfo.attach(results, total_count: total_count, per: scope.per, page: scope.page)
  end
end

#all(sql, *args, into: nil, &block) ⇒ Object

Runs a query, with optional arguments, and returns the result. If the SQL query returns rows with one column, this method returns an array of these values. Otherwise it returns an array of arrays.

Example:

  • Simple::SQL.all("SELECT id FROM users") returns an array of id values

  • Simple::SQL.all("SELECT id, email FROM users") returns an array of

    arrays `[ <id>, <email> ]`.
    

Simple::SQL.all “SELECT id, email FROM users” do |id, email|

# do something

end



39
40
41
42
43
44
45
46
# File 'lib/simple/sql/connection_adapter.rb', line 39

def all(sql, *args, into: nil, &block)
  result = exec_logged(sql, *args)
  result = enumerate(result, into: into, &block)
  if sql.is_a?(Scope) && sql.paginated?
    add_page_info(sql, result)
  end
  result
end

#ask(sql, *args, into: nil) ⇒ Object

Runs a query and returns the first result row of a query.

Examples:

  • Simple::SQL.ask "SELECT id FROM users WHERE email=$?", "foo@local" returns a number (or nil)

  • Simple::SQL.ask "SELECT id, email FROM users WHERE email=$?", "foo@local" returns an array [ <id>, <email> ] (or nil)



56
57
58
59
60
61
# File 'lib/simple/sql/connection_adapter.rb', line 56

def ask(sql, *args, into: nil)
  catch(:ok) do
    all(sql, *args, into: into) { |row| throw :ok, row }
    nil
  end
end

#enumerate(result, into:, &block) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/simple/sql/connection_adapter.rb', line 92

def enumerate(result, into:, &block)
  decoder = Decoder.new(self, result, into: into)

  if block
    result.each_row do |row|
      yield decoder.decode(row)
    end
    self
  else
    ary = []
    result.each_row { |row| ary << decoder.decode(row) }
    ary
  end
end

#exec(sql) ⇒ Object

execute one or more sql statements. This method does not allow to pass in arguments - since the pg client does not support this - but it allows to run multiple sql statements separated by “;”



19
20
21
22
23
# File 'lib/simple/sql/connection_adapter.rb', line 19

def exec(sql)
  Logging.yield_logged sql do
    raw_connection.exec sql
  end
end

#exec_logged(sql_or_scope, *args) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/simple/sql/connection_adapter.rb', line 77

def exec_logged(sql_or_scope, *args)
  if sql_or_scope.is_a?(Scope)
    raise ArgumentError, "You cannot call .all with a scope and additional arguments" unless args.empty?

    sql  = sql_or_scope.to_sql
    args = sql_or_scope.args
  else
    sql = sql_or_scope
  end

  Logging.yield_logged sql, *args do
    raw_connection.exec_params(sql, Encoder.encode_args(raw_connection, args))
  end
end

#resolve_type(ftype, fmod) ⇒ Object



107
108
109
110
# File 'lib/simple/sql/connection_adapter.rb', line 107

def resolve_type(ftype, fmod)
  @resolved_types ||= {}
  @resolved_types[[ftype, fmod]] ||= raw_connection.exec("SELECT format_type($1,$2)", [ftype, fmod]).getvalue(0, 0)
end