mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-12 22:21:50 +00:00
test(postgres): probe whether MAX() over text agrees across engines
DO NOT MERGE -- this exists to make CI answer a question.
The parity effort wrapped many descriptive text columns in Max() to satisfy
strict GROUP BY, justified as "Max() returns the value MariaDB picked
arbitrarily". Where the column genuinely varies within its group that does not
hold: Max() over text is a sort, and the engines sort text differently.
MariaDB's utf8mb4 collations fold case but treat punctuation and spaces as
significant. glibc's en_US.UTF-8 -- what the Linux CI Postgres runs -- ignores
punctuation at the primary level, so max('ITEM-C', 'ITEMB') should be 'ITEMB'
on MariaDB and 'ITEM-C' on Postgres.
These assertions encode MariaDB's answers. They pass on macOS (BSD/ICU
collation, which happens to agree). If the Linux Postgres job fails them, the
Max()-over-varying-text sites are a live parity gap and not only a
row-coherence one.
This commit is contained in:
35
erpnext/tests/test_text_collation_parity.py
Normal file
35
erpnext/tests/test_text_collation_parity.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import frappe
|
||||
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
|
||||
|
||||
def max_of(values):
|
||||
rows = " UNION ALL ".join(f"SELECT {frappe.db.escape(value)} AS v" for value in values)
|
||||
return frappe.db.sql(f"SELECT MAX(v) FROM ({rows}) t")[0][0]
|
||||
|
||||
|
||||
class TestTextCollationParity(ERPNextTestSuite):
|
||||
"""Does MAX() over text pick the same value on MariaDB and PostgreSQL?
|
||||
|
||||
The PostgreSQL parity effort wrapped many descriptive text columns in Max() to satisfy strict
|
||||
GROUP BY, on the reasoning that Max() returns the value MariaDB picked arbitrarily. Where the
|
||||
column genuinely varies within its group that reasoning does not hold: Max() over text is a
|
||||
sort, and the two engines sort text by different rules.
|
||||
|
||||
These expectations are MariaDB's (utf8mb4 case-insensitive collation: case folded, punctuation
|
||||
and spaces significant). A failure on the PostgreSQL job means the Max()-over-varying-text
|
||||
sites are a live parity gap, not only a row-coherence one.
|
||||
"""
|
||||
|
||||
def test_case_is_folded_not_byte_ordered(self):
|
||||
self.assertEqual(max_of(["apple", "Banana", "cherry"]), "cherry")
|
||||
self.assertEqual(max_of(["abc", "ABD"]), "ABD")
|
||||
|
||||
def test_punctuation_and_space_are_significant(self):
|
||||
# glibc en_US.UTF-8 ignores punctuation at the primary level and would answer "ITEM-C";
|
||||
# MariaDB compares '-' (0x2D) against 'B' (0x42) and answers "ITEMB"
|
||||
self.assertEqual(max_of(["ITEM-C", "ITEMB"]), "ITEMB")
|
||||
self.assertEqual(max_of(["Stores - TC", "StoresbTC"]), "StoresbTC")
|
||||
Reference in New Issue
Block a user