queries_controller.rb 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. module Blazer
  2. class QueriesController < BaseController
  3. before_action :set_queries, only: [:home, :index]
  4. before_action :set_query, only: [:show, :edit, :update, :destroy, :refresh]
  5. def home
  6. @queries = @queries.limit(1000)
  7. end
  8. def index
  9. render partial: "index", layout: false
  10. end
  11. def new
  12. @query = Blazer::Query.new(statement: params[:statement], data_source: params[:data_source])
  13. end
  14. def create
  15. @query = Blazer::Query.new(query_params)
  16. @query.creator = blazer_user
  17. if @query.save
  18. redirect_to query_path(@query, variable_params)
  19. else
  20. render :new
  21. end
  22. end
  23. def show
  24. @statement = @query.statement.dup
  25. process_vars(@statement)
  26. @smart_vars = {}
  27. @sql_errors = []
  28. data_source = Blazer.data_sources[@query.data_source]
  29. @bind_vars.each do |var|
  30. query = data_source.smart_variables[var]
  31. if query
  32. rows, error, cached_at = data_source.run_statement(query)
  33. @smart_vars[var] = rows.map { |v| v.values.reverse }
  34. @sql_errors << error if error
  35. end
  36. end
  37. end
  38. def edit
  39. end
  40. def run
  41. @statement = params[:statement]
  42. process_vars(@statement)
  43. @only_chart = params[:only_chart]
  44. if @success
  45. @query = Query.find_by(id: params[:query_id]) if params[:query_id]
  46. data_source = params[:data_source]
  47. data_source = @query.data_source if @query && @query.data_source
  48. # audit
  49. if Blazer.audit
  50. audit = Blazer::Audit.new(statement: @statement)
  51. audit.query = @query
  52. audit.data_source = data_source
  53. audit.user = blazer_user
  54. audit.save!
  55. end
  56. @data_source = Blazer.data_sources[data_source]
  57. @rows, @error, @cached_at = @data_source.run_statement(@statement, user: blazer_user, query: @query, refresh_cache: params[:check])
  58. if @query && !@error.to_s.include?("canceling statement due to statement timeout")
  59. @query.checks.each do |check|
  60. check.update_state(@rows, @error)
  61. end
  62. end
  63. @columns = {}
  64. if @rows.any?
  65. @rows.first.each do |key, value|
  66. @columns[key] =
  67. case value
  68. when Integer
  69. "int"
  70. when Float
  71. "float"
  72. else
  73. "string-ins"
  74. end
  75. end
  76. end
  77. @filename = @query.name.parameterize if @query
  78. @min_width_types = (@rows.first || {}).select { |k, v| v.is_a?(Time) || v.is_a?(String) || @data_source.smart_columns[k] }.keys
  79. @boom = {}
  80. @columns.keys.each do |key|
  81. query = @data_source.smart_columns[key]
  82. if query
  83. values = @rows.map { |r| r[key] }.compact.uniq
  84. rows, error, cached_at = @data_source.run_statement(ActiveRecord::Base.send(:sanitize_sql_array, [query.sub("{value}", "(?)"), values]))
  85. @boom[key] = Hash[rows.map(&:values)]
  86. end
  87. end
  88. @linked_columns = @data_source.linked_columns
  89. @markers = []
  90. [["latitude", "longitude"], ["lat", "lon"]].each do |keys|
  91. if (keys - (@rows.first || {}).keys).empty?
  92. @markers =
  93. @rows.select do |r|
  94. r[keys.first] && r[keys.last]
  95. end.map do |r|
  96. {
  97. title: r.except(*keys).map{ |k, v| "<strong>#{k}:</strong> #{v}" }.join("<br />").truncate(140),
  98. latitude: r[keys.first],
  99. longitude: r[keys.last]
  100. }
  101. end
  102. end
  103. end
  104. end
  105. respond_to do |format|
  106. format.html do
  107. render layout: false
  108. end
  109. format.csv do
  110. send_data csv_data(@rows), type: "text/csv; charset=utf-8; header=present", disposition: "attachment; filename=\"#{@query ? @query.name.parameterize : 'query'}.csv\""
  111. end
  112. end
  113. end
  114. def refresh
  115. data_source = Blazer.data_sources[@query.data_source]
  116. @statement = @query.statement.dup
  117. process_vars(@statement)
  118. data_source.clear_cache(@statement)
  119. redirect_to query_path(@query, variable_params)
  120. end
  121. def update
  122. if @query.update(query_params)
  123. redirect_to query_path(@query, variable_params)
  124. else
  125. render :edit
  126. end
  127. end
  128. def destroy
  129. @query.destroy
  130. redirect_to root_url
  131. end
  132. def tables
  133. @tables = Blazer.data_sources[params[:data_source]].tables.keys
  134. render partial: "tables", layout: false
  135. end
  136. private
  137. def set_queries
  138. @queries = Blazer::Query.order(:name)
  139. @queries = @queries.includes(:creator) if Blazer.user_class
  140. @trending_queries = Blazer::Audit.group(:query_id).where("created_at > ?", 2.days.ago).having("COUNT(DISTINCT user_id) >= 3").uniq.count(:user_id)
  141. @checks = Blazer::Check.group(:query_id).count
  142. end
  143. def set_query
  144. @query = Blazer::Query.find(params[:id].to_s.split("-").first)
  145. end
  146. def query_params
  147. params.require(:query).permit(:name, :description, :statement, :data_source)
  148. end
  149. def csv_data(rows)
  150. CSV.generate do |csv|
  151. if rows.any?
  152. csv << rows.first.keys
  153. end
  154. rows.each do |row|
  155. csv << row.values
  156. end
  157. end
  158. end
  159. end
  160. end