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:
@@ -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>
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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";
|
||||
}
|
||||
|
@@ -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]
|
||||
*/
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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}"
|
||||
|
Reference in New Issue
Block a user