1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-06 06:37:33 +02:00

PostgreSQL: Support index algorithms

This commit is contained in:
salacr
2025-04-16 09:07:53 +02:00
committed by Jakub Vrana
parent 6d6998c3d3
commit 92ce506243
9 changed files with 42 additions and 6 deletions

View File

@@ -2,6 +2,7 @@
- MySQL: Avoid warning on selecting tables with fulltext indexes (bug #1036)
- PostgreSQL, CockroachDB: Creating partitioned tables (bug #1031)
- PostgreSQL: Move partitioned tables from table list to parent table
- PostgreSQL: Support index algorithms (bug #1030)
- PostgreSQL: Support calling functions returning table (bug #1040)
- Designs: adminer.css with 'prefers-color-scheme: dark' don't disable dark mode
- Plugins: Method bodyClass() to add <body class>

View File

@@ -749,7 +749,7 @@ if (!defined('Adminer\DRIVER')) {
/** Run commands to alter indexes
* @param string $table escaped table name
* @param list<array{string, string, 'DROP'|list<string>}> $alter of ["index type", "name", ["column definition", ...]] or ["index type", "name", "DROP"]
* @param list<array{string, string, 'DROP'|list<string>, 3?: string}> $alter of ["index type", "name", ["column definition", ...], "algorithm"] or ["index type", "name", "DROP"]
* @return Result|bool
*/
function alter_indexes(string $table, $alter) {

View File

@@ -355,6 +355,14 @@ if (isset($_GET["pgsql"])) {
return "(SELECT oid FROM pg_class WHERE relnamespace = $this->nsOid AND relname = " . q($table) . " AND relkind IN ('r', 'm', 'v', 'f', 'p'))";
}
function indexMethods(): array {
static $methods = array();
if (!$methods) {
$methods = get_vals("SELECT amname FROM pg_am" . (min_version(9.6) ? " WHERE amtype = 'i'" : "") . " ORDER BY amname = 'btree' DESC, amname");
}
return $methods;
}
function supportsIndex(array $table_status): bool {
// returns true for "materialized view"
return $table_status["Engine"] != "view";
@@ -521,9 +529,10 @@ ORDER BY a.attnum") as $row
$table_oid = driver()->tableOid($table);
$columns = get_key_vals("SELECT attnum, attname FROM pg_attribute WHERE attrelid = $table_oid AND attnum > 0", $connection2);
foreach (
get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, (indpred IS NOT NULL)::int as indispartial
get_rows("SELECT relname, indisunique::int, indisprimary::int, indkey, indoption, (indpred IS NOT NULL)::int as indispartial, pg_am.amname as algorithm
FROM pg_index
JOIN pg_class ON indexrelid = oid
JOIN pg_am ON pg_am.oid = pg_class.relam
WHERE indrelid = $table_oid
ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row
) {
@@ -531,6 +540,7 @@ ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row
$return[$relname]["type"] = ($row["indispartial"] ? "INDEX" : ($row["indisprimary"] ? "PRIMARY" : ($row["indisunique"] ? "UNIQUE" : "INDEX")));
$return[$relname]["columns"] = array();
$return[$relname]["descs"] = array();
$return[$relname]["algorithm"] = $row["algorithm"];
if ($row["indkey"]) {
foreach (explode(" ", $row["indkey"]) as $indkey) {
$return[$relname]["columns"][] = $columns[$indkey];
@@ -711,7 +721,7 @@ ORDER BY conkey, conname") as $row
} elseif ($val[2] == "DROP") {
$drop[] = idf_escape($val[1]);
} else {
$queries[] = "CREATE INDEX " . idf_escape($val[1] != "" ? $val[1] : uniqid($table . "_")) . " ON " . table($table) . " (" . implode(", ", $val[2]) . ")";
$queries[] = "CREATE INDEX " . idf_escape($val[1] != "" ? $val[1] : uniqid($table . "_")) . " ON " . table($table) . ($val[3] ? " USING $val[3]" : "") . " (" . implode(", ", $val[2]) . ")";
}
}
if ($create) {

View File

@@ -360,7 +360,11 @@ class Adminer {
. ($index["descs"][$key] ? " DESC" : "")
;
}
echo "<tr title='" . h($name) . "'><th>$index[type]<td>" . implode(", ", $print) . "\n";
echo "<tr title='" . h($name) . "'>";
echo "<th>$index[type]" . ($index['algorithm'] != first(driver()->indexMethods()) ? " ($index[algorithm])" : "");
echo "<td>" . implode(", ", $print);
echo "\n";
}
echo "</table>\n";
}

View File

@@ -258,6 +258,14 @@ abstract class SqlDriver {
return !is_view($table_status);
}
/**
* Return list of supported index methods, first one is default
* @return list<string>
*/
function indexMethods(): array {
return array();
}
/** Get defined check constraints
* @return string[] [$name => $clause]
*/

View File

@@ -29,6 +29,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
$columns = array();
$lengths = array();
$descs = array();
$index_algorithm = (in_array($index["algorithm"], driver()->indexMethods()) ? $index["algorithm"] : "");
$set = array();
ksort($index["columns"]);
foreach ($index["columns"] as $key => $column) {
@@ -52,6 +53,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
&& array_values($existing["columns"]) === $columns
&& (!$existing["lengths"] || array_values($existing["lengths"]) === $lengths)
&& array_values($existing["descs"]) === $descs
&& $existing["algorithm"] === $index_algorithm
) {
// skip existing index
unset($indexes[$name]);
@@ -59,7 +61,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"]) {
}
}
if ($columns) {
$alter[] = array($index["type"], $name, $set);
$alter[] = array($index["type"], $name, $set, $index_algorithm);
}
}
}
@@ -105,6 +107,11 @@ $show_options = ($_POST ? $_POST["options"] : get_setting("index_options"));
<table class="nowrap">
<thead><tr>
<th id="label-type"><?php echo lang('Index Type'); ?>
<?php
if (driver()->indexMethods()) {
echo "<th id='label-method' class='idxopts" . ($show_options ? "" : " hidden") . "'>" . lang('Algorithm');
}
?>
<th><input type="submit" class="wayoff"><?php
echo lang('Columns') . ($lengths ? "<span class='idxopts" . ($show_options ? "" : " hidden") . "'> (" . lang('length') . ")</span>" : "");
if ($lengths || support("descidx")) {
@@ -128,6 +135,10 @@ foreach ($row["indexes"] as $index) {
if (!$_POST["drop_col"] || $j != key($_POST["drop_col"])) {
echo "<tr><td>" . html_select("indexes[$j][type]", array(-1 => "") + $index_types, $index["type"], ($j == count($row["indexes"]) ? "indexesAddRow.call(this);" : ""), "label-type");
if (driver()->indexMethods()) {
echo "<td class='idxopts" . ($show_options ? "" : " hidden") . "'>" . html_select("indexes[$j][algorithm]", array_merge(array(""), driver()->indexMethods()), $index['algorithm'], "label-method");
}
echo "<td>";
ksort($index["columns"]);
$i = 1;

View File

@@ -355,6 +355,7 @@ Lang::$translations = array(
'%s must <a%s>return an array</a>.' => '%s musí <a%s>vracet pole</a>.',
'<a%s>Configure</a> %s in %s.' => '<a%s>Nakonfigurujte</a> %s v %s.',
'screenshot' => 'obrázek',
'Algorithm' => 'Algoritmus',
);
// run `php ../../lang.php cs` to update this file

View File

@@ -357,6 +357,7 @@ Lang::$translations = array(
'%s must <a%s>return an array</a>.' => '%s xx <a%s>xx</a>.',
'<a%s>Configure</a> %s in %s.' => '<a%s>Xx</a> %s xx %s.',
'screenshot' => 'xx',
'Algorithm' => 'Xx',
);
// run `php ../../lang.php xx` to update this file

View File

@@ -65,7 +65,7 @@ parameters:
Field: "array{field?:string, full_type:string, type:string, length:numeric-string, unsigned:string, default?:string, null:bool, auto_increment:bool, collation:string, privileges:int[], comment:string, primary:bool, generated:string, orig?:string, on_update?:string, on_delete?:string, default_constraint?: string}"
FieldType: "array{type:string, length:numeric-string, unsigned:string, collation:string}" # subset of RoutineField and Field
RoutineField: "array{field:string, type:string, length:numeric-string, unsigned:string, null:bool, full_type:string, collation:string, inout?:string}"
Index: "array{type:string, columns:list<string>, lengths:list<numeric-string>, descs:list<?bool>}"
Index: "array{type:string, columns:list<string>, lengths:list<numeric-string>, descs:list<?bool>, algorithm?:string}"
ForeignKey: "array{db?:string, ns?:string, table:string, source:list<string>, target:list<?string>, on_delete:string, on_update?:string, definition?:string, deferrable?:string}"
Trigger: "array{Trigger?:string, Timing?:string, Event?:string, Of?:string, Type?:string, Statement?:string}"
Routine: "array{name?:string, fields:list<RoutineField>, comment:string, returns?:FieldType, definition:string, language?:string}"