From 6dec0d63b0c9e766c31ade96db93e3ef8125afa4 Mon Sep 17 00:00:00 2001 From: Jakub Vrana Date: Sat, 28 Jun 2025 22:11:03 +0200 Subject: [PATCH] New plugin: Specify query timeout --- CHANGELOG.md | 3 +- adminer/drivers/mysql.inc.php | 2 +- adminer/drivers/oracle.inc.php | 4 +++ adminer/include/adminer.inc.php | 4 +++ adminer/include/bootstrap.inc.php | 2 ++ adminer/include/driver.inc.php | 3 +- adminer/include/functions.inc.php | 6 ++-- editor/include/adminer.inc.php | 3 ++ plugins/menu-links.php | 4 +-- plugins/timeout.php | 48 +++++++++++++++++++++++++++++++ 10 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 plugins/timeout.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 606d3cfa..f6b35b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,9 @@ - PostgreSQL: Shorten values in hstore columns - PostgreSQL 11-: Avoid duplicate oid in table status (bug #1089) - Elasticsearch: Support dropping aliases -- Plugins: Methods processList() and killProcess() +- Plugins: Methods afterConnect(), processList() and killProcess() - New plugin: Display row numbers in select (bug #1106) +- New plugin: Specify query timeout ## Adminer 5.3.0 (released 2025-05-04) - Align numeric functions right diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index 0f5d850c..a626b91b 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -340,7 +340,7 @@ if (!defined('Adminer\DRIVER')) { function partitionsInfo(string $table): array { $from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table); - $result = connection()->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1"); + $result = $this->conn->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1"); $return = array(); list($return["partition_by"], $return["partition"], $return["partitions"]) = $result->fetch_row(); $partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION"); diff --git a/adminer/drivers/oracle.inc.php b/adminer/drivers/oracle.inc.php index af6d9b7c..90b53069 100644 --- a/adminer/drivers/oracle.inc.php +++ b/adminer/drivers/oracle.inc.php @@ -60,6 +60,10 @@ if (isset($_GET["oracle"])) { } return $return; } + + function timeout(int $ms): bool { + return oci_set_call_timeout($this->link, $ms); + } } class Result { diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php index a7395f75..21b3ddfe 100644 --- a/adminer/include/adminer.inc.php +++ b/adminer/include/adminer.inc.php @@ -85,6 +85,10 @@ class Adminer { return 2; } + /** Called after connecting and selecting a database */ + function afterConnect(): void { + } + /** Headers to send before HTML output */ function headers(): void { } diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index 223c565d..f4701d31 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -108,3 +108,5 @@ include "../adminer/include/xxtea.inc.php"; include "../adminer/include/auth.inc.php"; include "./include/editing.inc.php"; include "./include/connect.inc.php"; + +adminer()->afterConnect(); diff --git a/adminer/include/driver.inc.php b/adminer/include/driver.inc.php index 5568839a..cf13df13 100644 --- a/adminer/include/driver.inc.php +++ b/adminer/include/driver.inc.php @@ -253,8 +253,7 @@ abstract class SqlDriver { return !is_view($table_status); } - /** - * Return list of supported index algorithms, first one is default + /** Return list of supported index algorithms, first one is default * @param TableStatus $tableStatus * @return list */ diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 7c1ad839..2f75bcb5 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -338,11 +338,11 @@ function get_settings(string $cookie): array { } /** Get setting stored in a cookie +* @param mixed $default * @return mixed */ -function get_setting(string $key, string $cookie = "adminer_settings") { - $settings = get_settings($cookie); - return $settings[$key]; +function get_setting(string $key, string $cookie = "adminer_settings", $default = null) { + return idx(get_settings($cookie), $key, $default); } /** Store settings to a cookie diff --git a/editor/include/adminer.inc.php b/editor/include/adminer.inc.php index 6df24dcf..d54c524d 100644 --- a/editor/include/adminer.inc.php +++ b/editor/include/adminer.inc.php @@ -59,6 +59,9 @@ class Adminer { return 5; } + function afterConnect() { + } + function headers() { } diff --git a/plugins/menu-links.php b/plugins/menu-links.php index d3dc96e7..9c18d722 100644 --- a/plugins/menu-links.php +++ b/plugins/menu-links.php @@ -21,12 +21,12 @@ class AdminerMenuLinks extends Adminer\Plugin { '' => $this->lang('Both'), 'auto' => $this->lang('Auto (select on select page, structure otherwise)'), ); - $menu = Adminer\get_setting("menu", "adminer_config") ?: $this->menu; + $menu = Adminer\get_setting("menu", "adminer_config", $this->menu); return array($this->lang('Menu table links') => Adminer\html_radios('config[menu]', $options, $menu, "
")); } function tablesPrint(array $tables) { - $menu = Adminer\get_setting("menu", "adminer_config") ?: $this->menu; + $menu = Adminer\get_setting("menu", "adminer_config", $this->menu); $titles = array( 'select' => $this->lang('Select data'), 'table' => $this->lang('Show structure'), diff --git a/plugins/timeout.php b/plugins/timeout.php new file mode 100644 index 00000000..de5eb0d6 --- /dev/null +++ b/plugins/timeout.php @@ -0,0 +1,48 @@ +seconds = $seconds; + } + + function afterConnect() { + $seconds = Adminer\get_setting("timeout", "adminer_config", $this->seconds); + if ($seconds != '') { + $ms = $seconds * 1000; + $conn = Adminer\connection(); + switch (Adminer\JUSH) { + case 'sql': $conn->query("SET max_execution_time = $ms"); break; + case 'pgsql': $conn->query("SET statement_timeout = $ms"); break; + case 'mssql': $conn->query("SET LOCK_TIMEOUT $ms"); break; + default: + if (method_exists(connection(), 'timeout')) { + $conn->timeout($ms); + } + } + } + } + + function config() { + $seconds = Adminer\get_setting("timeout", "adminer_config", $this->seconds); + return array($this->lang('Queries timeout') => ' ' . $this->lang('seconds')); + } + + protected $translations = array( + 'cs' => array( + '' => 'Nastaví timeout pro spouštění každého dotazu', + 'Queries timeout' => 'Timeout dotazů', + 'seconds' => 'sekund', + ), + ); +}