Define a custom FIELD function to sort tables by list of ids without the emulation via string operations

This commit is contained in:
Jan Böhmer 2024-06-16 23:46:40 +02:00
parent d3dcefb645
commit 4f75e2641b
2 changed files with 13 additions and 3 deletions

View file

@ -199,6 +199,15 @@ final class Version20240606203053 extends AbstractMultiPlatformMigration impleme
$this->addSql('ALTER TABLE "users" ADD CONSTRAINT FK_1483A5E938248176 FOREIGN KEY (currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE webauthn_keys ADD CONSTRAINT FK_799FD143A76ED395 FOREIGN KEY (user_id) REFERENCES "users" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
//Create the FIELD() function for PostgreSQL
$this->addSql(<<<SQL
CREATE OR REPLACE FUNCTION FIELD(anyelement, VARIADIC anyarray) RETURNS bigint AS $$
SELECT n FROM (
SELECT row_number() OVER () AS n, x FROM unnest($2) x)
numbered WHERE numbered.x = $1;
$$ LANGUAGE SQL IMMUTABLE STRICT;
SQL);
//Create the initial groups and users
//Retrieve the json representations of the presets
$admin = $this->getJSONPermDataFromPreset(PermissionPresetsHelper::PRESET_ADMIN);

View file

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace App\Doctrine\Helpers;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\ORM\QueryBuilder;
/**
@ -44,11 +45,11 @@ final class FieldHelper
{
$db_platform = $qb->getEntityManager()->getConnection()->getDatabasePlatform();
//If we are on MySQL, we can just use the FIELD function
if ($db_platform instanceof AbstractMySQLPlatform) {
//If we are on MySQL, we can just use the FIELD function, for PostgreSQL we can use our custom defined one
if ($db_platform instanceof AbstractMySQLPlatform || $db_platform instanceof PostgreSQLPlatform) {
$param = (is_numeric($bound_param) ? '?' : ":") . (string) $bound_param;
$qb->orderBy("FIELD($field_expr, $param)", $order);
} else {
} else { //Use the sqlite/portable version
//Retrieve the values from the bound parameter
$param = $qb->getParameter($bound_param);
if ($param === null) {