diff --git a/adminer/check.inc.php b/adminer/check.inc.php index 05989ed6..c0c12341 100644 --- a/adminer/check.inc.php +++ b/adminer/check.inc.php @@ -24,7 +24,7 @@ if ($row && !$error) { page_header(($name != "" ? lang('Alter check') . ": " . h($name) : lang('Create check')), $error, array("table" => $TABLE)); if (!$row) { - $checks = $driver->checkConstraints($TABLE); + $checks = driver()->checkConstraints($TABLE); $row = array("name" => $name, "clause" => $checks[$name]); } ?> diff --git a/adminer/create.inc.php b/adminer/create.inc.php index 6ef46f4a..f7ae98e3 100644 --- a/adminer/create.inc.php +++ b/adminer/create.inc.php @@ -140,7 +140,7 @@ if ($_POST && !process_fields($row["fields"]) && !$error) { page_header(($TABLE != "" ? lang('Alter table') : lang('Create table')), $error, array("table" => $TABLE), h($TABLE)); if (!$_POST) { - $types = $driver->types(); + $types = driver()->types(); $row = array( "Engine" => $_COOKIE["adminer_engine"], "fields" => array(array("field" => "", "type" => (isset($types["int"]) ? "int" : (isset($types["integer"]) ? "integer" : "")), "on_update" => "")), @@ -171,7 +171,7 @@ $collations = collations(); if (is_array(reset($collations))) { $collations = call_user_func_array('array_merge', array_values($collations)); } -$engines = $driver->engines(); +$engines = driver()->engines(); // case of engine may differ foreach ($engines as $engine) { if (!strcasecmp($engine, $row["Engine"])) { diff --git a/adminer/db.inc.php b/adminer/db.inc.php index 93554519..39e5e499 100644 --- a/adminer/db.inc.php +++ b/adminer/db.inc.php @@ -69,7 +69,7 @@ if (adminer()->homepage()) { echo " \n"; echo "\n"; if ($_POST["search"] && $_POST["query"] != "") { - $_GET["where"][0]["op"] = $driver->convertOperator("LIKE %%"); + $_GET["where"][0]["op"] = driver()->convertOperator("LIKE %%"); search_tables(); } } diff --git a/adminer/download.inc.php b/adminer/download.inc.php index c9f7ddab..e2a8b5ec 100644 --- a/adminer/download.inc.php +++ b/adminer/download.inc.php @@ -6,7 +6,7 @@ $fields = fields($TABLE); header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=" . friendly_url("$TABLE-" . implode("_", $_GET["where"])) . "." . friendly_url($_GET["field"])); $select = array(idf_escape($_GET["field"])); -$result = $driver->select($TABLE, $select, array(where($_GET, $fields)), $select); +$result = driver()->select($TABLE, $select, array(where($_GET, $fields)), $select); $row = ($result ? $result->fetch_row() : array()); -echo $driver->value($row[0], $fields[$_GET["field"]]); +echo driver()->value($row[0], $fields[$_GET["field"]]); exit; // don't output footer diff --git a/adminer/drivers/mssql.inc.php b/adminer/drivers/mssql.inc.php index 63adc3b6..90a4778d 100644 --- a/adminer/drivers/mssql.inc.php +++ b/adminer/drivers/mssql.inc.php @@ -640,7 +640,6 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)) as $row } function create_sql($table, $auto_increment, $style) { - global $driver; if (is_view(table_status1($table))) { $view = view($table); return "CREATE VIEW " . table($table) . " AS $view[select]"; @@ -664,7 +663,7 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)) as $row $fields[] = ($index["type"] == "INDEX" ? "INDEX $name" : "CONSTRAINT $name " . ($index["type"] == "UNIQUE" ? "UNIQUE" : "PRIMARY KEY")) . " (" . implode(", ", $columns) . ")"; } } - foreach ($driver->checkConstraints($table) as $name => $check) { + foreach (driver()->checkConstraints($table) as $name => $check) { $fields[] = "CONSTRAINT " . idf_escape($name) . " CHECK ($check)"; } return "CREATE TABLE " . table($table) . " (\n\t" . implode(",\n\t", $fields) . "\n)"; diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index 0b252fdf..7c0a69c2 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -556,13 +556,12 @@ if (!defined('Adminer\DRIVER')) { * @return ForeignKey[] */ function foreign_keys(string $table): array { - global $driver; static $pattern = '(?:`(?:[^`]|``)+`|"(?:[^"]|"")+")'; $return = array(); $create_table = get_val("SHOW CREATE TABLE " . table($table), 1); if ($create_table) { preg_match_all( - "~CONSTRAINT ($pattern) FOREIGN KEY ?\\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($driver->onActions))?(?: ON UPDATE ($driver->onActions))?~", + "~CONSTRAINT ($pattern) FOREIGN KEY ?\\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE (driver()->onActions))?(?: ON UPDATE (driver()->onActions))?~", $create_table, $matches, PREG_SET_ORDER @@ -860,13 +859,12 @@ if (!defined('Adminer\DRIVER')) { * @return Routine */ function routine(string $name, string $type): array { - global $driver; $aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar"); $space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)"; - $enum = $driver->enumLength; - $type_pattern = "((" . implode("|", array_merge(array_keys($driver->types()), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$enum)++)\\))?" + $enum = driver()->enumLength; + $type_pattern = "((" . implode("|", array_merge(array_keys(driver()->types()), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$enum)++)\\))?" . "\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s,]+)['\"]?)?"; - $pattern = "$space*(" . ($type == "FUNCTION" ? "" : $driver->inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern"; + $pattern = "$space*(" . ($type == "FUNCTION" ? "" : driver()->inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern"; $create = get_val("SHOW CREATE $type " . idf_escape($name), 2); preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match); $fields = array(); diff --git a/adminer/drivers/pgsql.inc.php b/adminer/drivers/pgsql.inc.php index d4d0ff42..0795ecf7 100644 --- a/adminer/drivers/pgsql.inc.php +++ b/adminer/drivers/pgsql.inc.php @@ -484,7 +484,6 @@ ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row } function foreign_keys($table) { - global $driver; $return = array(); foreach ( get_rows("SELECT conname, condeferrable::int AS deferrable, pg_get_constraintdef(oid) AS definition @@ -500,8 +499,8 @@ ORDER BY conkey, conname") as $row $row['table'] = idf_unescape($match2[4]); } $row['target'] = array_map('Adminer\idf_unescape', array_map('trim', explode(',', $match[3]))); - $row['on_delete'] = (preg_match("~ON DELETE ($driver->onActions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION'); - $row['on_update'] = (preg_match("~ON UPDATE ($driver->onActions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION'); + $row['on_delete'] = (preg_match("~ON DELETE (driver()->onActions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION'); + $row['on_update'] = (preg_match("~ON UPDATE (driver()->onActions)~", $match[4], $match2) ? $match2[1] : 'NO ACTION'); $return[$row['conname']] = $row; } } @@ -793,12 +792,12 @@ AND typelem = 0" } function set_schema($schema, $connection2 = null) { - global $connection, $driver; + global $connection; if (!$connection2) { $connection2 = $connection; } $return = $connection2->query("SET search_path TO " . idf_escape($schema)); - $driver->setUserTypes(types()); //! get types from current_schemas('t') + driver()->setUserTypes(types()); //! get types from current_schemas('t') return $return; } @@ -820,7 +819,6 @@ AND typelem = 0" } function create_sql($table, $auto_increment, $style) { - global $driver; $return_parts = array(); $sequences = array(); @@ -872,7 +870,7 @@ AND typelem = 0" } } - foreach ($driver->checkConstraints($table) as $conname => $consrc) { + foreach (driver()->checkConstraints($table) as $conname => $consrc) { $return_parts[] = "CONSTRAINT " . idf_escape($conname) . " CHECK $consrc"; } diff --git a/adminer/drivers/sqlite.inc.php b/adminer/drivers/sqlite.inc.php index e4f7324b..27891dec 100644 --- a/adminer/drivers/sqlite.inc.php +++ b/adminer/drivers/sqlite.inc.php @@ -459,7 +459,6 @@ if (isset($_GET["sqlite"])) { * @param string $add_check CHECK constraint to add */ function recreate_table(string $table, string $name, array $fields, array $originals, array $foreign, int $auto_increment = 0, $indexes = array(), string $drop_check = "", string $add_check = ""): bool { - global $driver; if ($table != "") { if (!$fields) { foreach (fields($table) as $key => $field) { @@ -524,7 +523,7 @@ if (isset($_GET["sqlite"])) { $changes[] = " " . implode($field); } $changes = array_merge($changes, array_filter($foreign)); - foreach ($driver->checkConstraints($table) as $check) { + foreach (driver()->checkConstraints($table) as $check) { if ($check != $drop_check) { $changes[] = " CHECK ($check)"; } diff --git a/adminer/edit.inc.php b/adminer/edit.inc.php index 247066d6..68925ed3 100644 --- a/adminer/edit.inc.php +++ b/adminer/edit.inc.php @@ -27,7 +27,7 @@ if ($_POST && !$error && !isset($_GET["select"])) { queries_redirect( $location, lang('Item has been deleted.'), - $driver->delete($TABLE, $query_where, !$unique_array) + driver()->delete($TABLE, $query_where, !$unique_array) ); } else { @@ -46,7 +46,7 @@ if ($_POST && !$error && !isset($_GET["select"])) { queries_redirect( $location, lang('Item has been updated.'), - $driver->update($TABLE, $set, $query_where, !$unique_array) + driver()->update($TABLE, $set, $query_where, !$unique_array) ); if (is_ajax()) { page_headers(); @@ -54,7 +54,7 @@ if ($_POST && !$error && !isset($_GET["select"])) { exit; } } else { - $result = $driver->insert($TABLE, $set); + $result = driver()->insert($TABLE, $set); $last_id = ($result ? last_id($result) : 0); queries_redirect($location, lang('Item%s has been inserted.', ($last_id ? " $last_id" : "")), $result); //! link } @@ -77,7 +77,7 @@ if ($_POST["save"]) { $select = array("*"); } if ($select) { - $result = $driver->select($TABLE, $select, array($where), $select, array(), (isset($_GET["select"]) ? 2 : 1)); + $result = driver()->select($TABLE, $select, array($where), $select, array(), (isset($_GET["select"]) ? 2 : 1)); if (!$result) { $error = error(); } else { @@ -94,10 +94,10 @@ if ($_POST["save"]) { if (!support("table") && !$fields) { // used by Mongo and SimpleDB if (!$where) { // insert - $result = $driver->select($TABLE, array("*"), $where, array("*")); + $result = driver()->select($TABLE, array("*"), $where, array("*")); $row = ($result ? $result->fetch_assoc() : false); if (!$row) { - $row = array($driver->primary => ""); + $row = array(driver()->primary => ""); } } if ($row) { @@ -105,7 +105,7 @@ if (!support("table") && !$fields) { // used by Mongo and SimpleDB if (!$where) { $row[$key] = null; } - $fields[$key] = array("field" => $key, "null" => ($key != $driver->primary), "auto_increment" => ($key == $driver->primary)); + $fields[$key] = array("field" => $key, "null" => ($key != driver()->primary), "auto_increment" => ($key == driver()->primary)); } } } diff --git a/adminer/foreign.inc.php b/adminer/foreign.inc.php index d0a55445..792c12e6 100644 --- a/adminer/foreign.inc.php +++ b/adminer/foreign.inc.php @@ -101,8 +101,8 @@ foreach ($row["source"] as $key => $val) { ?>

-: "") + explode("|", $driver->onActions), $row["on_delete"]); ?> - : "") + explode("|", $driver->onActions), $row["on_update"]); ?> +: "") + explode("|", driver()->onActions), $row["on_delete"]); ?> + : "") + explode("|", driver()->onActions), $row["on_update"]); ?> "innodb-foreign-key-constraints.html", 'mariadb' => "foreign-keys/", diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php index a87900d8..0162a627 100644 --- a/adminer/include/adminer.inc.php +++ b/adminer/include/adminer.inc.php @@ -64,8 +64,7 @@ class Adminer { * @return list operators */ function operators(): array { - global $driver; - return $driver->operators; + return driver()->operators; } /** Get list of schemas @@ -175,7 +174,6 @@ class Adminer { * @param ?string $set new item options, NULL for no new item */ function selectLinks(array $tableStatus, ?string $set = ""): void { - global $driver; echo '

\n"; // required for IE9 inline edit - if (!$failed && ($warnings = $driver->warnings())) { + if (!$failed && ($warnings = driver()->warnings())) { $id = "warnings"; $return = ", " . lang('Warnings') . "" . script("qsl('a').onclick = partial(toggle, '$id');", "") . "$return\n" @@ -307,11 +304,10 @@ class Adminer { * @param TableStatus $tableStatus */ function tableStructurePrint(array $fields, array $tableStatus = null): void { - global $driver; echo "
\n"; echo "\n"; echo "\n"; - $structured_types = $driver->structuredTypes(); + $structured_types = driver()->structuredTypes(); foreach ($fields as $field) { echo "
" . lang('Column') . "" . lang('Type') . (support("comment") ? "" . lang('Comment') : "") . "
" . h($field["field"]); $type = h($field["full_type"]); @@ -357,7 +353,6 @@ class Adminer { * @param string[] $columns selectable columns */ function selectColumnsPrint(array $select, array $columns): void { - global $driver; print_fieldset("select", lang('Select'), $select); $i = 0; $select[""] = array(); @@ -369,7 +364,7 @@ class Adminer { $val["col"], ($key !== "" ? "selectFieldChange" : "selectAddRow") ); - echo "
" . ($driver->functions || $driver->grouping ? html_select("columns[$i][fun]", array(-1 => "") + array_filter(array(lang('Functions') => $driver->functions, lang('Aggregation') => $driver->grouping)), $val["fun"]) + echo "
" . (driver()->functions || driver()->grouping ? html_select("columns[$i][fun]", array(-1 => "") + array_filter(array(lang('Functions') => driver()->functions, lang('Aggregation') => driver()->grouping)), $val["fun"]) . on_help("event.target.value && event.target.value.replace(/ |\$/, '(') + ')'", 1) . script("qsl('select').onchange = function () { helpClose();" . ($key !== "" ? "" : " qsl('select, input', this.parentNode).onchange();") . " };", "") . "($column)" : $column) . "
\n"; @@ -507,13 +502,12 @@ class Adminer { * @return list> [[select_expressions], [group_expressions]] */ function selectColumnsProcess(array $columns, array $indexes): array { - global $driver; $select = array(); // select expressions, empty for * $group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used foreach ((array) $_GET["columns"] as $key => $val) { - if ($val["fun"] == "count" || ($val["col"] != "" && (!$val["fun"] || in_array($val["fun"], $driver->functions) || in_array($val["fun"], $driver->grouping)))) { + if ($val["fun"] == "count" || ($val["col"] != "" && (!$val["fun"] || in_array($val["fun"], driver()->functions) || in_array($val["fun"], driver()->grouping)))) { $select[$key] = apply_sql_function($val["fun"], ($val["col"] != "" ? idf_escape($val["col"]) : "*")); - if (!in_array($val["fun"], $driver->grouping)) { + if (!in_array($val["fun"], driver()->grouping)) { $group[] = $select[$key]; } } @@ -527,7 +521,7 @@ class Adminer { * @return list expressions to join by AND */ function selectSearchProcess(array $fields, array $indexes): array { - global $connection, $driver; + global $connection; $return = array(); foreach ($indexes as $i => $index) { if ($index["type"] == "FULLTEXT" && $_GET["fulltext"][$i] != "") { @@ -554,7 +548,7 @@ class Adminer { $cond .= " " . adminer()->processInput($fields[$val["col"]], $val["val"]); } if ($val["col"] != "") { - $return[] = $prefix . $driver->convertSearch(idf_escape($val["col"]), $val, $fields[$val["col"]]) . $cond; + $return[] = $prefix . driver()->convertSearch(idf_escape($val["col"]), $val, $fields[$val["col"]]) . $cond; } else { // find anywhere $cols = array(); @@ -565,7 +559,7 @@ class Adminer { && (!preg_match("~[\x80-\xFF]~", $val["val"]) || preg_match('~char|text|enum|set~', $field["type"])) && (!preg_match('~date|timestamp~', $field["type"]) || preg_match('~^\d+-\d+-\d+~', $val["val"])) ) { - $cols[] = $prefix . $driver->convertSearch(idf_escape($name), $val, $field) . $cond; + $cols[] = $prefix . driver()->convertSearch(idf_escape($name), $val, $field) . $cond; } } $return[] = ($cols ? "(" . implode(" OR ", $cols) . ")" : "1 = 0"); @@ -633,7 +627,6 @@ class Adminer { * @param string $time elapsed time */ function messageQuery(string $query, string $time, bool $failed = false): string { - global $driver; restart_session(); $history = &get_session("queries"); if (!idx($history, $_GET["db"])) { @@ -645,7 +638,7 @@ class Adminer { $history[$_GET["db"]][] = array($query, time(), $time); // not DB - $_GET["db"] is changed in database.inc.php //! respect $_GET["ns"] $sql_id = "sql-" . count($history[$_GET["db"]]); $return = "" . lang('SQL command') . "\n"; - if (!$failed && ($warnings = $driver->warnings())) { + if (!$failed && ($warnings = driver()->warnings())) { $id = "warnings-" . count($history[$_GET["db"]]); $return = "" . lang('Warnings') . ", $return\n"; } @@ -669,10 +662,9 @@ class Adminer { * @return list */ function editFunctions(array $field): array { - global $driver; $return = ($field["null"] ? "NULL/" : ""); $update = isset($_GET["select"]) || where($_GET); - foreach (array($driver->insertFunctions, $driver->editFunctions) as $key => $functions) { + foreach (array(driver()->insertFunctions, driver()->editFunctions) as $key => $functions) { if (!$key || (!isset($_GET["call"]) && $update)) { // relative functions foreach ($functions as $pattern => $val) { if (!$pattern || preg_match("~$pattern~", $field["type"])) { diff --git a/adminer/include/auth.inc.php b/adminer/include/auth.inc.php index 3485fcdf..5b1e510b 100644 --- a/adminer/include/auth.inc.php +++ b/adminer/include/auth.inc.php @@ -177,7 +177,7 @@ if (isset($_GET["username"]) && is_string(get_password())) { check_invalid_login($permanent); $connection = connect(adminer()->credentials()); if (is_object($connection)) { - $driver = new Driver($connection); + Driver::$instance = new Driver($connection); if ($connection->flavor) { save_settings(array("vendor-" . DRIVER . "-" . SERVER => get_driver(DRIVER))); } diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index 28164cd8..aae9e23c 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -39,7 +39,7 @@ if ($_GET["script"] == "version") { exit; } -global $connection, $driver, $translations; // allows including Adminer inside a function +global $connection, $translations; // allows including Adminer inside a function if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"]; diff --git a/adminer/include/driver.inc.php b/adminer/include/driver.inc.php index f122e0e0..59e477fc 100644 --- a/adminer/include/driver.inc.php +++ b/adminer/include/driver.inc.php @@ -12,8 +12,9 @@ function get_driver(string $id): string { } abstract class SqlDriver { - /** @var string[] */ static array $drivers = array(); - /** @var list */ static array $extensions = array(); // possible extensions + static Driver $instance; + /** @var string[] */ static array $drivers = array(); // all available drivers + /** @var list */ static array $extensions = array(); // possible extensions in the current driver static string $jush; // JUSH identifier protected Db $conn; diff --git a/adminer/include/editing.inc.php b/adminer/include/editing.inc.php index c5302218..92be3b1e 100644 --- a/adminer/include/editing.inc.php +++ b/adminer/include/editing.inc.php @@ -172,13 +172,12 @@ function json_row(string $key, $val = null): void { * @param list $extra_types extra types to prepend */ function edit_type(string $key, array $field, array $collations, array $foreign_keys = array(), array $extra_types = array()): void { - global $driver; $type = $field["type"]; echo "
" : '' ); - echo ($driver->unsigned ? "' : ''); + echo (driver()->unsigned ? "' : ''); echo (isset($field['on_update']) ? "' : '' ); echo ($foreign_keys - ? " " + ? " " : " " // space for IE ); } @@ -220,8 +219,7 @@ function get_partitions_info(string $table): array { /** Filter length value including enums */ function process_length(?string $length): string { - global $driver; - $enum_length = $driver->enumLength; + $enum_length = driver()->enumLength; return (preg_match("~^\\s*\\(?\\s*$enum_length(?:\\s*,\\s*$enum_length)*+\\s*\\)?\\s*\$~", $length) && preg_match_all("~$enum_length~", $length, $matches) ? "(" . implode(",", $matches[0]) . ")" : preg_replace('~^[0-9].*~', '(\0)', preg_replace('~[^-0-9,+()[\]]~', '', $length)) @@ -232,10 +230,9 @@ function process_length(?string $length): string { * @param FieldType $field */ function process_type(array $field, string $collate = "COLLATE"): string { - global $driver; return " $field[type]" . process_length($field["length"]) - . (preg_match(number_type(), $field["type"]) && in_array($field["unsigned"], $driver->unsigned) ? " $field[unsigned]" : "") + . (preg_match(number_type(), $field["type"]) && in_array($field["unsigned"], driver()->unsigned) ? " $field[unsigned]" : "") . (preg_match('~char|text|enum|set~', $field["type"]) && $field["collation"] ? " $collate " . (JUSH == "mssql" ? $field["collation"] : q($field["collation"])) : "") ; } @@ -265,10 +262,9 @@ function process_field(array $field, array $type_field): array { * @param Field $field */ function default_value(array $field): string { - global $driver; $default = $field["default"]; $generated = $field["generated"]; - return ($default === null ? "" : (in_array($generated, $driver->generated) + return ($default === null ? "" : (in_array($generated, driver()->generated) ? (JUSH == "mssql" ? " AS ($default)" . ($generated == "VIRTUAL" ? "" : " $generated") . "" : " GENERATED ALWAYS AS ($default) $generated") : " DEFAULT " . (!preg_match('~^GENERATED ~i', $default) && (preg_match('~char|binary|text|json|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default)) ? (JUSH == "sql" && preg_match('~text|json~', $field["type"]) ? "(" . q($default) . ")" : q($default)) // MySQL requires () around default value of text column @@ -302,7 +298,6 @@ function type_class(string $type) { * @param string[] $foreign_keys */ function edit_fields(array $fields, array $collations, $type = "TABLE", array $foreign_keys = array()): void { - global $driver; $fields = array_values($fields); $default_class = (($_POST ? $_POST["defaults"] : get_setting("defaults")) ? "" : " class='hidden'"); $comment_class = (($_POST ? $_POST["comments"] : get_setting("comments")) ? "" : " class='hidden'"); @@ -333,7 +328,7 @@ function edit_fields(array $fields, array $collations, $type = "TABLE", array $f $orig = $field[($_POST ? "orig" : "field")]; $display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !idx($_POST["drop_col"], $i))) && (support("drop_col") || $orig == ""); echo "\n"; - echo ($type == "PROCEDURE" ? "" . html_select("fields[$i][inout]", explode("|", $driver->inout), $field["inout"]) : "") . ""; + echo ($type == "PROCEDURE" ? "" . html_select("fields[$i][inout]", explode("|", driver()->inout), $field["inout"]) : "") . ""; if ($display) { echo ""; } @@ -342,8 +337,8 @@ function edit_fields(array $fields, array $collations, $type = "TABLE", array $f if ($type == "TABLE") { echo "" . checkbox("fields[$i][null]", 1, $field["null"], "", "", "block", "label-null"); echo ""; - echo "" . ($driver->generated - ? html_select("fields[$i][generated]", array_merge(array("", "DEFAULT"), $driver->generated), $field["generated"]) . " " + echo "" . (driver()->generated + ? html_select("fields[$i][generated]", array_merge(array("", "DEFAULT"), driver()->generated), $field["generated"]) . " " : checkbox("fields[$i][generated]", 1, $field["generated"], "", "", "", "label-default") ); echo ""; @@ -472,13 +467,12 @@ function create_trigger(string $on, array $row): string { * @param Routine $row */ function create_routine($routine, array $row): string { - global $driver; $set = array(); $fields = (array) $row["fields"]; ksort($fields); // enforce fields order foreach ($fields as $field) { if ($field["field"] != "") { - $set[] = (preg_match("~^($driver->inout)\$~", $field["inout"]) ? "$field[inout] " : "") . idf_escape($field["field"]) . process_type($field, "CHARACTER SET"); + $set[] = (preg_match("~^(driver()->inout)\$~", $field["inout"]) ? "$field[inout] " : "") . idf_escape($field["field"]) . process_type($field, "CHARACTER SET"); } } $definition = rtrim($row["definition"], ";"); @@ -500,7 +494,6 @@ function remove_definer(string $query): string { * @param ForeignKey $foreign_key */ function format_foreign_key(array $foreign_key): string { - global $driver; $db = $foreign_key["db"]; $ns = $foreign_key["ns"]; return " FOREIGN KEY (" . implode(", ", array_map('Adminer\idf_escape', $foreign_key["source"])) . ") REFERENCES " @@ -508,8 +501,8 @@ function format_foreign_key(array $foreign_key): string { . ($ns != "" && $ns != $_GET["ns"] ? idf_escape($ns) . "." : "") . idf_escape($foreign_key["table"]) . " (" . implode(", ", array_map('Adminer\idf_escape', $foreign_key["target"])) . ")" //! reuse $name - check in older MySQL versions - . (preg_match("~^($driver->onActions)\$~", $foreign_key["on_delete"]) ? " ON DELETE $foreign_key[on_delete]" : "") - . (preg_match("~^($driver->onActions)\$~", $foreign_key["on_update"]) ? " ON UPDATE $foreign_key[on_update]" : "") + . (preg_match("~^(driver()->onActions)\$~", $foreign_key["on_delete"]) ? " ON DELETE $foreign_key[on_delete]" : "") + . (preg_match("~^(driver()->onActions)\$~", $foreign_key["on_update"]) ? " ON UPDATE $foreign_key[on_update]" : "") ; } diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 80c40678..593bea19 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -19,8 +19,7 @@ function adminer() { /** Get Driver object */ function driver(): Driver { - global $driver; - return $driver; + return Driver::$instance; } /** Unescape database identifier @@ -601,7 +600,6 @@ function column_foreign_keys(string $table): array { * @return Field[] same as fields() */ function fields_from_edit(): array { // used by Mongo and SimpleDB - global $driver; $return = array(); foreach ((array) $_POST["field_keys"] as $key => $val) { if ($val != "") { @@ -616,7 +614,7 @@ function fields_from_edit(): array { // used by Mongo and SimpleDB "field" => $name, "privileges" => array("insert" => 1, "update" => 1, "where" => 1, "order" => 1), "null" => 1, - "auto_increment" => ($key == $driver->primary), + "auto_increment" => ($key == driver()->primary), ); } return $return; @@ -830,10 +828,9 @@ function count_rows(string $table, array $where, bool $is_group, array $group): * @return string[] */ function slow_query(string $query): array { - global $driver; $db = adminer()->database(); $timeout = adminer()->queryTimeout(); - $slow_query = $driver->slowQuery($query, $timeout); + $slow_query = driver()->slowQuery($query, $timeout); $connection2 = null; if (!$slow_query && support("kill")) { $connection2 = connect(adminer()->credentials()); diff --git a/adminer/include/html.inc.php b/adminer/include/html.inc.php index b897bde9..7f744151 100644 --- a/adminer/include/html.inc.php +++ b/adminer/include/html.inc.php @@ -189,7 +189,6 @@ function enum_input(string $type, string $attrs, array $field, $value, string $e * @param mixed $value */ function input(array $field, $value, ?string $function, ?bool $autofocus = false): void { - global $driver; $name = h(bracket_escape($field["field"])); echo ""; if (is_array($value) && !$function) { @@ -203,12 +202,12 @@ function input(array $field, $value, ?string $function, ?bool $autofocus = false $functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + adminer()->editFunctions($field); $disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : ""; $attrs = " name='fields[$name]'$disabled" . ($autofocus ? " autofocus" : ""); - $enums = $driver->enumLength($field); + $enums = driver()->enumLength($field); if ($enums) { $field["type"] = "enum"; $field["length"] = $enums; } - echo $driver->unconvertFunction($field) . " "; + echo driver()->unconvertFunction($field) . " "; $table = $_GET["edit"] ?: $_GET["select"]; if ($field["type"] == "enum") { echo h($functions[""]) . "" . adminer()->editInput($table, $field, $attrs, $value); @@ -247,7 +246,7 @@ function input(array $field, $value, ?string $function, ?bool $autofocus = false echo "" . h($value) . ''; } else { // int(3) is only a display hint - $types = $driver->types(); + $types = driver()->types(); $maxlength = (!preg_match('~int~', $field["type"]) && preg_match('~^(\d+)(,(\d+))?$~', $field["length"], $match) ? ((preg_match("~binary~", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0) @@ -283,14 +282,13 @@ function input(array $field, $value, ?string $function, ?bool $autofocus = false * @return mixed false to leave the original value */ function process_input(array $field) { - global $driver; if (stripos($field["default"], "GENERATED ALWAYS AS ") === 0) { return; } $idf = bracket_escape($field["field"]); $function = idx($_POST["function"], $idf); $value = $_POST["fields"][$idf]; - if ($field["type"] == "enum" || $driver->enumLength($field)) { + if ($field["type"] == "enum" || driver()->enumLength($field)) { if ($value == -1) { return false; } @@ -323,7 +321,7 @@ function process_input(array $field) { if (!is_string($file)) { return false; //! report errors } - return $driver->quoteBinary($file); + return driver()->quoteBinary($file); } return adminer()->processInput($field, $value, $function); } diff --git a/adminer/select.inc.php b/adminer/select.inc.php index b9ce4d8c..04ac30f2 100644 --- a/adminer/select.inc.php +++ b/adminer/select.inc.php @@ -46,7 +46,7 @@ if ($_GET["val"] && is_ajax()) { $as = convert_field($fields[key($row)]); $select = array($as ?: idf_escape(key($row))); $where[] = where_check($unique_idf, $fields); - $return = $driver->select($TABLE, $select, $where, $select); + $return = driver()->select($TABLE, $select, $where, $select); if ($return) { echo first($return->fetch_row()); } @@ -121,10 +121,10 @@ if ($_POST && !$error) { $query = ($_POST["clone"] ? "INTO " . table($TABLE) . " (" . implode(", ", array_keys($set)) . ")\nSELECT " . implode(", ", $set) . "\nFROM " . table($TABLE) : ""); if ($_POST["all"] || ($primary && is_array($_POST["check"])) || $is_group) { $result = ($_POST["delete"] - ? $driver->delete($TABLE, $where_check) + ? driver()->delete($TABLE, $where_check) : ($_POST["clone"] - ? queries("INSERT $query$where_check" . $driver->insertReturning($TABLE)) - : $driver->update($TABLE, $set, $where_check) + ? queries("INSERT $query$where_check" . driver()->insertReturning($TABLE)) + : driver()->update($TABLE, $set, $where_check) ) ); $affected = $connection->affected_rows; @@ -136,10 +136,10 @@ if ($_POST && !$error) { // where is not unique so OR can't be used $where2 = "\nWHERE " . ($where ? implode(" AND ", $where) . " AND " : "") . where_check($val, $fields); $result = ($_POST["delete"] - ? $driver->delete($TABLE, $where2, 1) + ? driver()->delete($TABLE, $where2, 1) : ($_POST["clone"] ? queries("INSERT" . limit1($TABLE, $query, $where2)) - : $driver->update($TABLE, $set, $where2, 1) + : driver()->update($TABLE, $set, $where2, 1) ) ); if (!$result) { @@ -176,7 +176,7 @@ if ($_POST && !$error) { $key = bracket_escape($key, true); // true - back $set[idf_escape($key)] = (preg_match('~char|text~', $fields[$key]["type"]) || $val != "" ? adminer()->processInput($fields[$key], $val) : "NULL"); } - $result = $driver->update( + $result = driver()->update( $TABLE, $set, " WHERE " . ($where ? implode(" AND ", $where) . " AND " : "") . where_check($unique_idf, $fields), @@ -201,7 +201,7 @@ if ($_POST && !$error) { $cols = array_keys($fields); preg_match_all('~(?>"[^"]*"|[^"\r\n]+)+~', $file, $matches); $affected = count($matches[0]); - $driver->begin(); + driver()->begin(); $separator = ($_POST["separator"] == "csv" ? "," : ($_POST["separator"] == "tsv" ? "\t" : ";")); $rows = array(); foreach ($matches[0] as $key => $val) { @@ -218,12 +218,12 @@ if ($_POST && !$error) { $rows[] = $set; } } - $result = (!$rows || $driver->insertUpdate($TABLE, $rows, $primary)); + $result = (!$rows || driver()->insertUpdate($TABLE, $rows, $primary)); if ($result) { - $driver->commit(); + driver()->commit(); } queries_redirect(remove_from_uri("page"), lang('%d row(s) have been imported.', $affected), $result); - $driver->rollback(); // after queries_redirect() to not overwrite error + driver()->rollback(); // after queries_redirect() to not overwrite error } } @@ -299,7 +299,7 @@ if (!$columns && support("table")) { } } } - $result = $driver->select($TABLE, $select2, $where, $group2, $order, $limit, $page, true); + $result = driver()->select($TABLE, $select2, $where, $group2, $order, $limit, $page, true); if (!$result) { echo "

" . error() . "\n"; @@ -411,7 +411,7 @@ if (!$columns && support("table")) { foreach ($row as $key => $val) { if (isset($names[$key])) { $field = $fields[$key]; - $val = $driver->value($val, $field); + $val = driver()->value($val, $field); if ($val != "" && (!isset($email_fields[$key]) || $email_fields[$key] != "")) { $email_fields[$key] = (is_mail($val) ? $names[$key] : ""); //! filled e-mails can be contained on other pages } diff --git a/adminer/sql.inc.php b/adminer/sql.inc.php index ce9867d0..e0a84dd6 100644 --- a/adminer/sql.inc.php +++ b/adminer/sql.inc.php @@ -85,7 +85,7 @@ if (!$error && $_POST) { $offset = $pos + strlen($found); if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end - $c_style_escapes = $driver->hasCStyleEscapes() || (JUSH == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e")); + $c_style_escapes = driver()->hasCStyleEscapes() || (JUSH == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e")); $pattern = ($found == '/*' ? '\*/' : ($found == '[' ? ']' @@ -146,7 +146,7 @@ if (!$error && $_POST) { . (strlen($q) < 1000 ? " " . lang('Edit') . "" : "") // 1000 - maximum length of encoded URL in IE is 2083 characters ; $affected = $connection->affected_rows; // getting warnings overwrites this - $warnings = ($_POST["only_errors"] ? "" : $driver->warnings()); + $warnings = ($_POST["only_errors"] ? "" : driver()->warnings()); $warnings_id = "warnings-$commands"; if ($warnings) { $time .= ", " . lang('Warnings') . "" . script("qsl('a').onclick = partial(toggle, '$warnings_id');", ""); diff --git a/adminer/table.inc.php b/adminer/table.inc.php index bd65acac..4388c550 100644 --- a/adminer/table.inc.php +++ b/adminer/table.inc.php @@ -26,7 +26,7 @@ if ($fields) { adminer()->tableStructurePrint($fields, $table_status); } -if (support("indexes") && $driver->supportsIndex($table_status)) { +if (support("indexes") && driver()->supportsIndex($table_status)) { echo "

" . lang('Indexes') . "

\n"; $indexes = indexes($TABLE); if ($indexes) { @@ -68,7 +68,7 @@ if (!is_view($table_status)) { if (support("check")) { echo "

" . lang('Checks') . "

\n"; - $check_constraints = $driver->checkConstraints($TABLE); + $check_constraints = driver()->checkConstraints($TABLE); if ($check_constraints) { echo "\n"; foreach ($check_constraints as $key => $val) { diff --git a/adminer/type.inc.php b/adminer/type.inc.php index 8b2d839a..6c4633c2 100644 --- a/adminer/type.inc.php +++ b/adminer/type.inc.php @@ -24,7 +24,7 @@ if (!$row) {

types(); + $types = driver()->types(); $enums = type_values($types[$TYPE]); if ($enums) { echo "ENUM (" . h($enums) . ")\n

"; diff --git a/editor/include/adminer.inc.php b/editor/include/adminer.inc.php index 6becf73b..ac3ef4fb 100644 --- a/editor/include/adminer.inc.php +++ b/editor/include/adminer.inc.php @@ -354,7 +354,6 @@ ORDER BY ORDINAL_POSITION", null, "") as $row } function selectSearchProcess($fields, $indexes) { - global $driver; $return = array(); foreach ((array) $_GET["where"] as $key => $where) { $col = $where["col"]; @@ -370,7 +369,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row } else { $text_type = preg_match('~char|text|enum|set~', $field["type"]); $value = adminer()->processInput($field, (!$op && $text_type && preg_match('~^[^%]+$~', $val) ? "%$val%" : $val)); - $conds[] = $driver->convertSearch($name, $where, $field) . ($value == "NULL" ? " IS" . ($op == ">=" ? " NOT" : "") . " $value" + $conds[] = driver()->convertSearch($name, $where, $field) . ($value == "NULL" ? " IS" . ($op == ">=" ? " NOT" : "") . " $value" : (in_array($op, adminer()->operators()) || $op == "=" ? " $op $value" : ($text_type ? " LIKE $value" : " IN (" . str_replace(",", "', '", $value) . ")"