Skip to content

Commit dea062e

Browse files
committed
Rework index column introspection on Postgres
1 parent feed861 commit dea062e

File tree

1 file changed

+26
-50
lines changed

1 file changed

+26
-50
lines changed

src/Schema/PostgreSQLSchemaManager.php

Lines changed: 26 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
use function str_contains;
2424
use function str_replace;
2525
use function strtolower;
26-
use function trim;
2726

2827
use const CASE_LOWER;
2928

@@ -162,44 +161,19 @@ protected function _getPortableTableDefinition(array $table): string
162161
*/
163162
protected function _getPortableTableIndexesList(array $rows, string $tableName): array
164163
{
165-
$buffer = [];
166-
foreach ($rows as $row) {
167-
$colNumbers = array_map('intval', explode(' ', $row['indkey']));
168-
$columnNameSql = sprintf(
169-
<<<'SQL'
170-
SELECT attnum,
171-
quote_ident(attname) AS attname
172-
FROM pg_attribute
173-
WHERE attrelid = %d
174-
AND attnum IN (%s)
175-
ORDER BY attnum
176-
SQL,
177-
$row['indrelid'],
178-
implode(', ', $colNumbers),
179-
);
180-
181-
// @phpstan-ignore missingType.checkedException
182-
$indexColumns = $this->connection->fetchAllAssociative($columnNameSql);
183-
184-
// required for getting the order of the columns right.
185-
foreach ($colNumbers as $colNum) {
186-
foreach ($indexColumns as $colRow) {
187-
if ($colNum !== $colRow['attnum']) {
188-
continue;
189-
}
190-
191-
$buffer[] = [
192-
'key_name' => $row['relname'],
193-
'column_name' => trim($colRow['attname']),
194-
'non_unique' => ! $row['indisunique'],
195-
'primary' => $row['indisprimary'],
196-
'where' => $row['where'],
197-
];
198-
}
199-
}
200-
}
201-
202-
return parent::_getPortableTableIndexesList($buffer, $tableName);
164+
return parent::_getPortableTableIndexesList(array_map(
165+
/** @param array<string, mixed> $row */
166+
static function (array $row): array {
167+
return [
168+
'key_name' => $row['relname'],
169+
'non_unique' => ! $row['indisunique'],
170+
'primary' => $row['indisprimary'],
171+
'where' => $row['where'],
172+
'column_name' => $row['attname'],
173+
];
174+
},
175+
$rows,
176+
), $tableName);
203177
}
204178

205179
/**
@@ -496,24 +470,26 @@ protected function selectIndexColumns(string $databaseName, ?string $tableName =
496470
$sql = sprintf(
497471
<<<'SQL'
498472
SELECT
499-
quote_ident(tn.nspname) AS schema_name,
500-
quote_ident(tc.relname) AS table_name,
473+
quote_ident(n.nspname) AS schema_name,
474+
quote_ident(c.relname) AS table_name,
501475
quote_ident(ic.relname) AS relname,
502476
i.indisunique,
503477
i.indisprimary,
504478
i.indkey,
505479
i.indrelid,
506-
pg_get_expr(indpred, indrelid) AS "where"
480+
pg_get_expr(indpred, indrelid) AS "where",
481+
quote_ident(attname) AS attname
507482
FROM pg_index i
508-
JOIN pg_class AS tc ON tc.oid = i.indrelid
509-
JOIN pg_namespace tn ON tn.oid = tc.relnamespace
483+
JOIN pg_class AS c ON c.oid = i.indrelid
484+
JOIN pg_namespace n ON n.oid = c.relnamespace
510485
JOIN pg_class AS ic ON ic.oid = i.indexrelid
511-
WHERE ic.oid IN (
512-
SELECT indexrelid
513-
FROM pg_index i
514-
JOIN pg_class AS c ON c.oid = i.indrelid
515-
JOIN pg_namespace n ON n.oid = c.relnamespace
516-
WHERE %s)
486+
JOIN LATERAL UNNEST(i.indkey) WITH ORDINALITY AS keys(attnum, ord)
487+
ON TRUE
488+
JOIN pg_attribute a
489+
ON a.attrelid = c.oid
490+
AND a.attnum = keys.attnum
491+
WHERE %s
492+
ORDER BY 1, 2, keys.ord;
517493
SQL,
518494
implode(' AND ', $this->buildQueryConditions($tableName, $params)),
519495
);

0 commit comments

Comments
 (0)