Skip to content

Commit

Permalink
deduplicate queries using template
Browse files Browse the repository at this point in the history
  • Loading branch information
toy committed Oct 10, 2024
1 parent 3e2c1e9 commit 74aaecc
Showing 1 changed file with 33 additions and 183 deletions.
216 changes: 33 additions & 183 deletions app/models/custom_field/order_statements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
#++

module CustomField::OrderStatements
USER_ORDER_COLUMN = "ARRAY[users.lastname, users.firstname, users.mail]".freeze

# Returns a ORDER BY clause that can used to sort customized
# objects by their value of the custom field.
# Returns false, if the custom field can not be used for sorting.
Expand Down Expand Up @@ -82,214 +80,66 @@ def group_by_join_statement

private

def join_for_order_by_string
def join_for_order(value:, join: nil, multi_value: false)
<<-SQL.squish
LEFT OUTER JOIN (
SELECT DISTINCT ON (cv.customized_id) cv.customized_id, cv.value "value"
SELECT
#{multi_value ? '' : 'DISTINCT ON (cv.customized_id)'}
cv.customized_id,
#{value} "value"
FROM #{CustomValue.quoted_table_name} cv
#{join}
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
ORDER BY cv.customized_id, cv.id
#{multi_value ? 'GROUP BY cv.customized_id' : 'ORDER BY cv.customized_id, cv.id'}
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
end

def join_for_order_by_int
<<-SQL.squish
LEFT OUTER JOIN (
SELECT DISTINCT ON (cv.customized_id) cv.customized_id, cv.value::decimal(60) "value"
FROM #{CustomValue.quoted_table_name} cv
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
ORDER BY cv.customized_id, cv.id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
end
def join_for_order_by_string = join_for_order(value: "cv.value")

def join_for_order_by_float
<<-SQL.squish
LEFT OUTER JOIN (
SELECT DISTINCT ON (cv.customized_id) cv.customized_id, cv.value::double precision "value"
FROM #{CustomValue.quoted_table_name} cv
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
ORDER BY cv.customized_id, cv.id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
end
def join_for_order_by_int = join_for_order(value: "cv.value::decimal(60)")

def join_for_order_by_list
if multi_value?
join_for_order_by_multi_value_list
else
join_for_order_by_single_value_list
end
end
def join_for_order_by_float = join_for_order(value: "cv.value::double precision")

def join_for_order_by_single_value_list
<<-SQL.squish
LEFT OUTER JOIN (
SELECT DISTINCT ON (cv.customized_id) cv.customized_id, co.position "value"
FROM #{CustomValue.quoted_table_name} cv
INNER JOIN #{CustomOption.quoted_table_name} co
ON co.id = cv.value::bigint
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
ORDER BY cv.customized_id, cv.id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
end

def join_for_order_by_multi_value_list
<<-SQL.squish
LEFT OUTER JOIN (
SELECT cv.customized_id, array_agg(co.position ORDER BY co.position) "value"
FROM #{CustomValue.quoted_table_name} cv
INNER JOIN #{CustomOption.quoted_table_name} co
ON co.id = cv.value::bigint
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
GROUP BY cv.customized_id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
def join_for_order_by_list
join_for_order(
value: multi_value? ? "ARRAY_AGG(co.position ORDER BY co.position)" : "co.position",
join: "INNER JOIN #{CustomOption.quoted_table_name} co ON co.id = cv.value::bigint",
multi_value:
)
end

def join_for_group_by_list
if multi_value?
join_for_group_by_multi_value_list
join_for_order(
value: "ARRAY_TO_STRING(ARRAY_AGG(cv.value ORDER BY co.position), '.')",
join: "INNER JOIN #{CustomOption.quoted_table_name} co ON co.id = cv.value::bigint",
multi_value:
)
else
join_for_group_by_single_value_list
join_for_order_by_string
end
end

def join_for_group_by_single_value_list
<<-SQL.squish
LEFT OUTER JOIN (
SELECT DISTINCT ON (cv.customized_id) cv.customized_id, cv.value "value"
FROM #{CustomValue.quoted_table_name} cv
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
ORDER BY cv.customized_id, cv.id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
end

def join_for_group_by_multi_value_list
<<-SQL.squish
LEFT OUTER JOIN (
SELECT cv.customized_id, array_to_string(array_agg(cv.value ORDER BY co.position), '.') "value"
FROM #{CustomValue.quoted_table_name} cv
INNER JOIN #{CustomOption.quoted_table_name} co
ON co.id = cv.value::bigint
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
GROUP BY cv.customized_id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
end

def join_for_order_by_user
if multi_value?
join_for_order_by_multi_value_user
else
join_for_order_by_single_value_user
end
end

def join_for_order_by_single_value_user
<<-SQL.squish
LEFT OUTER JOIN (
SELECT DISTINCT ON (cv.customized_id) cv.customized_id, #{USER_ORDER_COLUMN} "value"
FROM #{CustomValue.quoted_table_name} cv
INNER JOIN #{User.quoted_table_name} users
ON users.id = cv.value::bigint
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
ORDER BY cv.customized_id, cv.id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
end
columns_array = "ARRAY[users.lastname, users.firstname, users.mail]"

def join_for_order_by_multi_value_user
<<-SQL.squish
LEFT OUTER JOIN (
SELECT cv.customized_id, ARRAY_AGG(#{USER_ORDER_COLUMN} ORDER BY #{USER_ORDER_COLUMN}) "value"
FROM #{CustomValue.quoted_table_name} cv
INNER JOIN #{User.quoted_table_name} users
ON users.id = cv.value::bigint
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
GROUP BY cv.customized_id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
join_for_order(
value: multi_value? ? "ARRAY_AGG(#{columns_array} ORDER BY #{columns_array})" : columns_array,
join: "INNER JOIN #{User.quoted_table_name} users ON users.id = cv.value::bigint",
multi_value:
)
end

def join_for_order_by_version
if multi_value?
join_for_order_by_multi_value_version
else
join_for_order_by_single_value_version
end
end

def join_for_order_by_single_value_version
<<-SQL.squish
LEFT OUTER JOIN (
SELECT DISTINCT ON (cv.customized_id) cv.customized_id, versions.name "value"
FROM #{CustomValue.quoted_table_name} cv
INNER JOIN #{Version.quoted_table_name} versions
ON versions.id = cv.value::bigint
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
ORDER BY cv.customized_id, cv.id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
end

def join_for_order_by_multi_value_version
<<-SQL.squish
LEFT OUTER JOIN (
SELECT cv.customized_id, array_agg(versions.name ORDER BY versions.name) "value"
FROM #{CustomValue.quoted_table_name} cv
INNER JOIN #{Version.quoted_table_name} versions
ON versions.id = cv.value::bigint
WHERE cv.customized_type = #{CustomValue.connection.quote(self.class.customized_class.name)}
AND cv.custom_field_id = #{id}
AND cv.value IS NOT NULL
AND cv.value != ''
GROUP BY cv.customized_id
) cf_order_#{id}
ON cf_order_#{id}.customized_id = #{self.class.customized_class.quoted_table_name}.id
SQL
join_for_order(
value: multi_value? ? "array_agg(versions.name ORDER BY versions.name)" : "versions.name",
join: "INNER JOIN #{Version.quoted_table_name} versions ON versions.id = cv.value::bigint",
multi_value:
)
end
end

0 comments on commit 74aaecc

Please sign in to comment.