sql_helper.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. class SqlHelper
  3. def initialize(object:, table_name: nil)
  4. @object = object
  5. @table_name = table_name
  6. end
  7. def db_column(column)
  8. "#{ActiveRecord::Base.connection.quote_table_name(@table_name || @object.table_name)}.#{ActiveRecord::Base.connection.quote_column_name(column)}"
  9. end
  10. def db_value(value)
  11. ActiveRecord::Base.connection.quote_string(value)
  12. end
  13. def get_param_key(key, params)
  14. sort_by = []
  15. if params[key].present? && params[key].is_a?(String)
  16. params[key] = params[key].split(%r{\s*,\s*})
  17. elsif params[key].blank?
  18. params[key] = []
  19. end
  20. sort_by
  21. end
  22. =begin
  23. This function will check the params for the "sort_by" attribute
  24. and validate its values.
  25. sql_helper = SqlHelper.new(object: Ticket)
  26. sort_by = sql_helper.get_sort_by(params, default)
  27. returns
  28. sort_by = [
  29. 'created_at',
  30. 'updated_at',
  31. ]
  32. =end
  33. def get_sort_by(params, default = nil)
  34. sort_by = get_param_key(:sort_by, params)
  35. # check order
  36. params[:sort_by].each do |value|
  37. # only accept values which are set for the db schema
  38. raise "Found invalid column '#{value}' for sorting." if @object.columns_hash[value].blank?
  39. sort_by.push(value)
  40. end
  41. if sort_by.blank? && default.present?
  42. if default.is_a?(Array)
  43. sort_by = default
  44. else
  45. sort_by.push(default)
  46. end
  47. end
  48. sort_by
  49. end
  50. =begin
  51. This function will check the params for the "order_by" attribute
  52. and validate its values.
  53. sql_helper = SqlHelper.new(object: Ticket)
  54. order_by = sql_helper.get_order_by(params, default)
  55. returns
  56. order_by = [
  57. 'asc',
  58. 'desc',
  59. ]
  60. =end
  61. def get_order_by(params, default = nil)
  62. order_by = get_param_key(:order_by, params)
  63. # check order
  64. params[:order_by].each do |value|
  65. raise "Found invalid order by value #{value}. Please use 'asc' or 'desc'." if !value.match?(%r{\A(asc|desc)\z}i)
  66. order_by.push(value.downcase)
  67. end
  68. if order_by.blank? && default.present?
  69. if default.is_a?(Array)
  70. order_by = default
  71. else
  72. order_by.push(default)
  73. end
  74. end
  75. order_by
  76. end
  77. def set_sql_order_default(sql, default)
  78. if sql.blank? && default.present?
  79. sql.push(db_column(default))
  80. end
  81. sql
  82. end
  83. =begin
  84. This function will use the evaluated values for sort_by and
  85. order_by to generate the ORDER-SELECT sql statement for the sorting
  86. of the result.
  87. sort_by = [ 'created_at', 'updated_at' ]
  88. order_by = [ 'asc', 'desc' ]
  89. default = 'tickets.created_at'
  90. sql_helper = SqlHelper.new(object: Ticket)
  91. sql = sql_helper.get_order_select(sort_by, order_by, default)
  92. returns
  93. sql = 'tickets.created_at, tickets.updated_at'
  94. =end
  95. def get_order_select(sort_by, order_by, default = nil)
  96. sql = []
  97. sort_by.each_with_index do |value, index|
  98. next if value.blank?
  99. next if order_by[index].blank?
  100. sql.push(db_column(value))
  101. end
  102. sql = set_sql_order_default(sql, default)
  103. sql.join(', ')
  104. end
  105. =begin
  106. This function will use the evaluated values for sort_by and
  107. order_by to generate the ORDER- sql statement for the sorting
  108. of the result.
  109. sort_by = [ 'created_at', 'updated_at' ]
  110. order_by = [ 'asc', 'desc' ]
  111. default = 'tickets.created_at DESC'
  112. sql_helper = SqlHelper.new(object: Ticket)
  113. sql = sql_helper.get_order(sort_by, order_by, default)
  114. returns
  115. sql = 'tickets.created_at ASC, tickets.updated_at DESC'
  116. =end
  117. def get_order(sort_by, order_by, default = nil)
  118. sql = []
  119. sort_by.each_with_index do |value, index|
  120. next if value.blank?
  121. next if order_by[index].blank?
  122. sql.push("#{db_column(value)} #{order_by[index]}")
  123. end
  124. sql = set_sql_order_default(sql, default)
  125. sql.join(', ')
  126. end
  127. def containable?(attribute)
  128. ObjectManager::Attribute.for_object(@object).exists?(name: attribute, data_type: %w[multiselect multi_tree_select])
  129. end
  130. def array_contains_all(attribute, value, negated: false)
  131. value = [''] if value.blank?
  132. value = Array(value)
  133. result = if Rails.application.config.db_column_array
  134. "(#{db_column(attribute)} @> ARRAY[#{value.map { |v| "'#{db_value(v)}'" }.join(',')}]::varchar[])"
  135. else
  136. "JSON_CONTAINS(#{db_column(attribute)}, '#{db_value(value.to_json)}', '$')"
  137. end
  138. negated ? "NOT(#{result})" : "(#{result})"
  139. end
  140. def array_contains_one(attribute, value, negated: false)
  141. value = [''] if value.blank?
  142. value = Array(value)
  143. result = if Rails.application.config.db_column_array
  144. "(#{db_column(attribute)} && ARRAY[#{value.map { |v| "'#{db_value(v)}'" }.join(',')}]::varchar[])"
  145. else
  146. value.map { |v| "JSON_CONTAINS(#{db_column(attribute)}, '#{db_value(v.to_json)}', '$')" }.join(' OR ')
  147. end
  148. negated ? "NOT(#{result})" : "(#{result})"
  149. end
  150. end