Disambiguate `Address.state_province_id:abbr` (MySQL; simpler version)
authorTim Otten <totten@civicrm.org>
Fri, 10 Feb 2023 22:40:55 +0000 (14:40 -0800)
committerTim Otten <totten@civicrm.org>
Fri, 17 Feb 2023 06:51:13 +0000 (22:51 -0800)
Consider `ContactJoinTest::testCreateWithPrimaryAndBilling` which writes the value:

  'address_billing.state_province_id:abbr' => 'AK',

The symbol 'AK' can map to three places: Akwa Ibom (Nigeria), Atakora
(Benin), and Alaska (USA).  This is an ambiguous choice.  It should be
resolved in a consistent way.

One flavor of ambiguity comes from MySQL.  When loading abbreviations, Civi
queries with `ORDER BY abbreviation`.  This is a *typically* stable, but it
has no *guaranteed* resolution.  Adding a secondary sort key makes the
outcome clear/unambiguous.

CRM/Core/PseudoConstant.php

index 4e3b97c0c18cf29e600b9526406421014aa10ec2..3159f677257838a17739cb9ff777f3fa104e38b2 100644 (file)
@@ -1500,6 +1500,10 @@ WHERE  id = %1
     $from = 'FROM %3';
     $wheres = [];
     $order = 'ORDER BY %2';
+    if (in_array('id', $availableFields, TRUE)) {
+      // Example: 'ORDER BY abbreviation, id' because `abbreviation`s are not unique.
+      $order .= ', id';
+    }
 
     // Use machine name in certain contexts
     if ($context === 'validate' || $context === 'match') {