module RunningCount::Statement

Public Class Methods

prepare_statement(counter_data) click to toggle source
# File lib/running_count/statement.rb, line 17
def prepare_statement(counter_data)
  return if ActiveRecord::Base.connection.exec_query("select name from pg_prepared_statements where name = '#{counter_data[:statement]}'").present?

  ActiveRecord::Base.connection.exec_query(counter_data[:statement_sql])
rescue ActiveRecord::StatementInvalid
  Rails.logger.warn "Statement already exists: #{counter_data[:statement]}"
end
reconcile_item(item, counter_data) click to toggle source
# File lib/running_count/statement.rb, line 29
def reconcile_item(item, counter_data)
  Storage.clear_item(item, counter_data[:running_set_name])

  destination_id = Format.parse(item)
  ActiveRecord::Base.connection.exec_query("EXECUTE #{counter_data[:statement]}(#{destination_id})")
end
release_statement(counter_data) click to toggle source
# File lib/running_count/statement.rb, line 25
def release_statement(counter_data)
  ActiveRecord::Base.connection.exec_query(counter_data[:release_sql])
end
statement_sql(table_name, statement, destination_table_name, set_name, relation, opts) click to toggle source
# File lib/running_count/statement.rb, line 8
def statement_sql(table_name, statement, destination_table_name, set_name, relation, opts)
  basic_sql(
    statement,
    destination_table_name,
    set_name,
    inner_sql(table_name, relation, opts),
  )
end

Private Class Methods

basic_sql(statement, destination_table_name, set_name, inner_sql) click to toggle source
# File lib/running_count/statement.rb, line 84
def basic_sql(statement, destination_table_name, set_name, inner_sql)
  # source_table is the table where the counted values are coming from
  # destination_table is the table where the counted values are being saved
  #
  %(
    PREPARE #{statement} (int) AS
    UPDATE "#{destination_table_name}"
    SET "#{set_name}" = (
      #{inner_sql}
    ),
    "updated_at" = now()
    WHERE "#{destination_table_name}"."id" = $1
  )
end
count_inner_sql(table_name, relation, opts) click to toggle source
# File lib/running_count/statement.rb, line 64
def count_inner_sql(table_name, relation, opts)
  %(
    SELECT COUNT(*) FROM "#{table_name}"
    WHERE "#{table_name}"."#{relation}_id" = $1
    #{extra_sql(opts)}
  )
end
count_statement_sql(table_name, statement, destination_table_name, set_name, relation, opts) click to toggle source
# File lib/running_count/statement.rb, line 78
def count_statement_sql(table_name, statement, destination_table_name, set_name, relation, opts)
  inner_sql = count_inner_sql(table_name, relation, opts)

  basic_sql(statement, destination_table_name, set_name, inner_sql)
end
extra_sql(opts) click to toggle source
# File lib/running_count/statement.rb, line 38
def extra_sql(opts)
  if opts[:sql]
    opts[:sql].map { |sql| "AND #{sql}" }.join(" ")
  else
    nil
  end
end
inner_sql(table_name, relation, opts) click to toggle source
# File lib/running_count/statement.rb, line 46
def inner_sql(table_name, relation, opts)
  if opts[:scope]
    opts[:scope].call
  elsif opts[:aggregated_field]
    sum_inner_sql(table_name, relation, opts)
  else
    count_inner_sql(table_name, relation, opts)
  end
end
sum_inner_sql(table_name, relation, opts) click to toggle source
# File lib/running_count/statement.rb, line 56
def sum_inner_sql(table_name, relation, opts)
  %(
    SELECT COALESCE(SUM(#{opts[:aggregated_field]}), 0) FROM "#{table_name}"
    WHERE "#{table_name}"."#{relation}_id" = $1
    #{extra_sql(opts)}
  )
end
sum_statement_sql(table_name, statement, destination_table_name, set_name, relation, opts) click to toggle source
# File lib/running_count/statement.rb, line 72
def sum_statement_sql(table_name, statement, destination_table_name, set_name, relation, opts)
  inner_sql = sum_inner_sql(table_name, relation, opts)

  basic_sql(statement, destination_table_name, set_name, inner_sql)
end