Skip to content

Commit 0e0da50

Browse files
aidanharanAidan Haran
and
Aidan Haran
authored
Coerce some calculation tests (#910)
Co-authored-by: Aidan Haran <aharan@fusioneer.com>
1 parent df110e8 commit 0e0da50

File tree

1 file changed

+103
-2
lines changed

1 file changed

+103
-2
lines changed

test/cases/coerced_tests.rb

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,112 @@ def test_offset_is_kept_coerced
318318
original_test_offset_is_kept
319319
end
320320

321-
# Are decimal, not integer.
321+
# The SQL Server `AVG()` function for a list of integers returns an integer (not a decimal).
322322
coerce_tests! :test_should_return_decimal_average_of_integer_field
323323
def test_should_return_decimal_average_of_integer_field_coerced
324324
value = Account.average(:id)
325-
assert_equal BigDecimal("3.0").to_s, BigDecimal(value).to_s
325+
assert_equal 3, value
326+
end
327+
328+
# In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
329+
# Match SQL Server limit implementation.
330+
coerce_tests! :test_select_avg_with_group_by_as_virtual_attribute_with_sql
331+
def test_select_avg_with_group_by_as_virtual_attribute_with_sql_coerced
332+
rails_core = companies(:rails_core)
333+
334+
sql = <<~SQL
335+
SELECT firm_id, AVG(CAST(credit_limit AS DECIMAL)) AS avg_credit_limit
336+
FROM accounts
337+
WHERE firm_id = ?
338+
GROUP BY firm_id
339+
ORDER BY firm_id
340+
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
341+
SQL
342+
343+
account = Account.find_by_sql([sql, rails_core]).first
344+
345+
# id was not selected, so it should be nil
346+
# (cannot select id because it wasn't used in the GROUP BY clause)
347+
assert_nil account.id
348+
349+
# firm_id was explicitly selected, so it should be present
350+
assert_equal(rails_core, account.firm)
351+
352+
# avg_credit_limit should be present as a virtual attribute
353+
assert_equal(52.5, account.avg_credit_limit)
354+
end
355+
356+
# In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
357+
# Order column must be in the GROUP clause.
358+
coerce_tests! :test_select_avg_with_group_by_as_virtual_attribute_with_ar
359+
def test_select_avg_with_group_by_as_virtual_attribute_with_ar_coerced
360+
rails_core = companies(:rails_core)
361+
362+
account = Account
363+
.select(:firm_id, "AVG(CAST(credit_limit AS DECIMAL)) AS avg_credit_limit")
364+
.where(firm: rails_core)
365+
.group(:firm_id)
366+
.order(:firm_id)
367+
.take!
368+
369+
# id was not selected, so it should be nil
370+
# (cannot select id because it wasn't used in the GROUP BY clause)
371+
assert_nil account.id
372+
373+
# firm_id was explicitly selected, so it should be present
374+
assert_equal(rails_core, account.firm)
375+
376+
# avg_credit_limit should be present as a virtual attribute
377+
assert_equal(52.5, account.avg_credit_limit)
378+
end
379+
380+
# In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
381+
# SELECT columns must be in the GROUP clause.
382+
# Match SQL Server limit implementation.
383+
coerce_tests! :test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_sql
384+
def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_sql_coerced
385+
rails_core = companies(:rails_core)
386+
387+
sql = <<~SQL
388+
SELECT companies.*, AVG(CAST(accounts.credit_limit AS DECIMAL)) AS avg_credit_limit
389+
FROM companies
390+
INNER JOIN accounts ON companies.id = accounts.firm_id
391+
WHERE companies.id = ?
392+
GROUP BY companies.id, companies.type, companies.firm_id, companies.firm_name, companies.name, companies.client_of, companies.rating, companies.account_id, companies.description
393+
ORDER BY companies.id
394+
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
395+
SQL
396+
397+
firm = DependentFirm.find_by_sql([sql, rails_core]).first
398+
399+
# all the DependentFirm attributes should be present
400+
assert_equal rails_core, firm
401+
assert_equal rails_core.name, firm.name
402+
403+
# avg_credit_limit should be present as a virtual attribute
404+
assert_equal(52.5, firm.avg_credit_limit)
405+
end
406+
407+
408+
# In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
409+
# SELECT columns must be in the GROUP clause.
410+
coerce_tests! :test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar
411+
def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar_coerced
412+
rails_core = companies(:rails_core)
413+
414+
firm = DependentFirm
415+
.select("companies.*", "AVG(CAST(accounts.credit_limit AS DECIMAL)) AS avg_credit_limit")
416+
.where(id: rails_core)
417+
.joins(:account)
418+
.group(:id, :type, :firm_id, :firm_name, :name, :client_of, :rating, :account_id, :description)
419+
.take!
420+
421+
# all the DependentFirm attributes should be present
422+
assert_equal rails_core, firm
423+
assert_equal rails_core.name, firm.name
424+
425+
# avg_credit_limit should be present as a virtual attribute
426+
assert_equal(52.5, firm.avg_credit_limit)
326427
end
327428

328429
# Match SQL Server limit implementation

0 commit comments

Comments
 (0)