diff --git a/app/DB.php b/app/DB.php index 1a3a208e35e..5b1258e5a8e 100644 --- a/app/DB.php +++ b/app/DB.php @@ -41,4 +41,21 @@ public static function caseInsensitiveLikeOperator(): string return 'LIKE'; } + + /** + * @internal + */ + public static function groupConcat(string $column): string + { + switch (DB::connection()->getDriverName()) { + case 'pgsql': + case 'sqlsrv': + return 'STRING_AGG(' . $column . ", ',')"; + + case 'mysql': + case 'sqlite': + default: + return 'GROUP_CONCAT(' . $column . ')'; + } + } } diff --git a/app/Services/AdminService.php b/app/Services/AdminService.php index 7da328812cd..f4761029a02 100644 --- a/app/Services/AdminService.php +++ b/app/Services/AdminService.php @@ -39,10 +39,13 @@ use League\Flysystem\StorageAttributes; use function array_map; +use function array_unique; use function explode; use function fclose; use function fread; +use function implode; use function preg_match; +use function sort; /** * Utilities for the control panel. @@ -117,7 +120,7 @@ public function duplicateRecords(Tree $tree): array ->where('s_file', '=', $tree->id()) ->groupBy(['s_name']) ->having(new Expression('COUNT(s_id)'), '>', '1') - ->select([new Expression('GROUP_CONCAT(s_id) AS xrefs')]) + ->select([new Expression(DB::groupConcat('s_id') . ' AS xrefs')]) ->orderBy('xrefs') ->pluck('xrefs') ->map(static function (string $xrefs) use ($tree): array { @@ -127,6 +130,14 @@ public function duplicateRecords(Tree $tree): array }) ->all(); + // Database agnostic way to do GROUP_CONCAT(DISTINCT x ORDER BY x) + $distinct_order_by = static function (string $xrefs): string { + $array = explode(',', $xrefs); + sort($array); + + return implode(',', array_unique($array)); + }; + $individuals = DB::table('dates') ->join('name', static function (JoinClause $join): void { $join @@ -137,10 +148,11 @@ public function duplicateRecords(Tree $tree): array ->whereIn('d_fact', ['BIRT', 'CHR', 'BAPM', 'DEAT', 'BURI']) ->groupBy(['d_year', 'd_month', 'd_day', 'd_type', 'd_fact', 'n_type', 'n_full']) ->having(new Expression('COUNT(DISTINCT d_gid)'), '>', '1') - ->select([new Expression('GROUP_CONCAT(DISTINCT d_gid ORDER BY d_gid) AS xrefs')]) - ->distinct() + ->select([new Expression(DB::groupConcat('d_gid') . ' AS xrefs')]) ->orderBy('xrefs') ->pluck('xrefs') + ->map($distinct_order_by) + ->unique() ->map(static function (string $xrefs) use ($tree): array { return array_map(static function (string $xref) use ($tree): Individual { return Registry::individualFactory()->make($xref, $tree); @@ -153,7 +165,7 @@ public function duplicateRecords(Tree $tree): array ->groupBy([new Expression('LEAST(f_husb, f_wife)')]) ->groupBy([new Expression('GREATEST(f_husb, f_wife)')]) ->having(new Expression('COUNT(f_id)'), '>', '1') - ->select([new Expression('GROUP_CONCAT(f_id) AS xrefs')]) + ->select([new Expression(DB::groupConcat('f_id') . ' AS xrefs')]) ->orderBy('xrefs') ->pluck('xrefs') ->map(static function (string $xrefs) use ($tree): array { @@ -168,7 +180,7 @@ public function duplicateRecords(Tree $tree): array ->where('descriptive_title', '<>', '') ->groupBy(['descriptive_title']) ->having(new Expression('COUNT(DISTINCT m_id)'), '>', '1') - ->select([new Expression('GROUP_CONCAT(m_id) AS xrefs')]) + ->select([new Expression(DB::groupConcat('m_id') .' AS xrefs')]) ->orderBy('xrefs') ->pluck('xrefs') ->map(static function (string $xrefs) use ($tree): array {