MySQL: Fix saving empty enum (fix #1152)

This commit is contained in:
Jakub Vrana
2025-09-07 17:57:09 +02:00
parent b1c825484d
commit d1831641a9
4 changed files with 32 additions and 26 deletions

View File

@@ -10,6 +10,7 @@
- Autofocus added field in alter table
- Executed SQL commands: Add button for copy to clipboard
- Load more: run syntax highlighter
- MySQL: Fix saving empty enum (bug #1152)
- MySQL 5.0-: Do not load partitioning info in alter table (bug #1099)
- MariaDB: Parse COLLATE in routine definition (bug #1104)
- PostgreSQL: Show structure of inherited tables

View File

@@ -717,13 +717,13 @@ class Adminer {
* @param ?string $table null in call.inc.php
* @param Field $field
* @param string $attrs attributes to use inside the tag
* @param string|string[]|false|null $value false means original value
* @return string custom input field or empty string for default
*/
function editInput(?string $table, array $field, string $attrs, ?string $value): string {
function editInput(?string $table, array $field, string $attrs, $value): string {
if ($field["type"] == "enum") {
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
. ($field["null"] ? "<label><input type='radio'$attrs value=''" . ($value !== null || isset($_GET["select"]) ? "" : " checked") . "><i>NULL</i></label> " : "")
. enum_input("radio", $attrs, $field, $value, $value === 0 ? 0 : null) // 0 - empty value
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='orig' checked><i>" . lang('original') . "</i></label> " : "")
. enum_input("radio", $attrs, $field, $value, "NULL")
;
}
return "";

View File

@@ -179,15 +179,17 @@ function hidden_fields_get(): void {
/** Print enum or set input field
* @param 'radio'|'checkbox' $type
* @param Field $field
* @param mixed $value string|array
* @param string|string[]|false|null $value false means original value
*/
function enum_input(string $type, string $attrs, array $field, $value, ?string $empty = null): string {
function enum_input(string $type, string $attrs, array $field, $value, string $empty = ""): string {
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
$return = ($empty !== null ? "<label><input type='$type'$attrs value='$empty'" . ((is_array($value) ? in_array($empty, $value) : $value === $empty) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : "");
foreach ($matches[1] as $i => $val) {
$prefix = ($field["type"] == "enum" ? "val-" : "");
$checked = (is_array($value) ? in_array("null", $value) : $value === null);
$return = ($field["null"] && $prefix ? "<label><input type='$type'$attrs value='null'" . ($checked ? " checked" : "") . "><i>$empty</i></label>" : "");
foreach ($matches[1] as $val) {
$val = stripcslashes(str_replace("''", "'", $val));
$checked = (is_array($value) ? in_array($val, $value) : $value === $val);
$return .= " <label><input type='$type'$attrs value='" . h($val) . "'" . ($checked ? ' checked' : '') . '>' . h(adminer()->editVal($val, $field)) . '</label>';
$checked = (is_array($value) ? in_array($prefix . $val, $value) : $value === $val);
$return .= " <label><input type='$type'$attrs value='" . h($prefix . $val) . "'" . ($checked ? ' checked' : '') . '>' . h(adminer()->editVal($val, $field)) . '</label>';
}
return $return;
}
@@ -208,13 +210,13 @@ function input(array $field, $value, ?string $function, ?bool $autofocus = false
$function = null;
}
$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);
if ($enums) {
$field["type"] = "enum";
$field["length"] = $enums;
}
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
$attrs = " name='fields[$name]" . ($field["type"] == "enum" || $field["type"] == "set" ? "[]" : "") . "'$disabled" . ($autofocus ? " autofocus" : "");
echo driver()->unconvertFunction($field) . " ";
$table = $_GET["edit"] ?: $_GET["select"];
if ($field["type"] == "enum") {
@@ -234,12 +236,7 @@ function input(array $field, $value, ?string $function, ?bool $autofocus = false
echo "<input type='hidden'$attrs value='0'>"
. "<input type='checkbox'" . (preg_match('~^(1|t|true|y|yes|on)$~i', $value) ? " checked='checked'" : "") . "$attrs value='1'>";
} elseif ($field["type"] == "set") {
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val));
$checked = in_array($val, explode(",", $value), true);
echo " <label><input type='checkbox' name='fields[$name][$i]' value='" . h($val) . "'" . ($checked ? ' checked' : '') . ">" . h(adminer()->editVal($val, $field)) . '</label>';
}
echo enum_input("checkbox", $attrs, $field, (is_string($value) ? explode(",", $value) : $value));
} elseif (is_blob($field) && ini_bool("file_uploads")) {
echo "<input type='file' name='fields-$name'>";
} elseif ($function == "json" || preg_match('~^jsonb?$~', $field["type"])) {
@@ -297,12 +294,14 @@ function process_input(array $field) {
$function = idx($_POST["function"], $idf);
$value = idx($_POST["fields"], $idf);
if ($field["type"] == "enum" || driver()->enumLength($field)) {
if ($value == -1) {
$value = $value[0];
if ($value == "orig") {
return false;
}
if ($value == "") {
if ($value == "null") {
return "NULL";
}
$value = substr($value, 4); // 4 - strlen("val-")
}
if ($field["auto_increment"] && $value == "") {
return null;

View File

@@ -217,7 +217,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
}
function selectVal($val, $link, $field, $original) {
$return = $val;
$return = "$val";
$link = h($link);
if (is_blob($field) && !is_utf8($val)) {
$return = lang('%d byte(s)', strlen($original));
@@ -264,14 +264,14 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
$fields = fields($_GET["select"]);
foreach ($columns as $name => $desc) {
$field = $fields[$name];
if (preg_match("~enum~", $field["type"]) || like_bool($field)) { //! set - uses 1 << $i and FIND_IN_SET()
if ($field["type"] == "enum" || like_bool($field)) { //! set - uses 1 << $i and FIND_IN_SET()
$key = $keys[$name];
$i--;
echo "<div>" . h($desc) . ":" . input_hidden("where[$i][col]", $name);
$val = idx($where[$key], "val");
echo (like_bool($field)
? "<select name='where[$i][val]'>" . optionlist(array("" => "", lang('no'), lang('yes')), $val, true) . "</select>"
: enum_input("checkbox", " name='where[$i][val][]'", $field, (array) $val, ($field["null"] ? 0 : null))
: enum_input("checkbox", " name='where[$i][val][]'", $field, (array) $val, lang('empty'))
);
echo "</div>\n";
unset($columns[$name]);
@@ -369,7 +369,13 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
if ($col != "" || is_numeric($val) || !preg_match(number_type(), $field["type"])) {
$name = idf_escape($name);
if ($col != "" && $field["type"] == "enum") {
$conds[] = (in_array(0, $val) ? "$name IS NULL OR " : "") . "$name IN (" . implode(", ", array_map('Adminer\q', $val)) . ")";
$in = array();
foreach ($val as $val1) {
if (preg_match('~val-~', $val1)) {
$in[] = q(substr($val1, 4));
}
}
$conds[] = (in_array("null", $val) ? "$name IS NULL OR " : "") . ($in ? "$name IN (" . implode(", ", $in) . ")" : "0");
} else {
$text_type = preg_match('~char|text|enum|set~', $field["type"]);
$value = adminer()->processInput($field, (!$op && $text_type && preg_match('~^[^%]+$~', $val) ? "%$val%" : $val));
@@ -459,8 +465,8 @@ ORDER BY ORDINAL_POSITION", null, "") as $row
function editInput($table, $field, $attrs, $value) {
if ($field["type"] == "enum") {
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
. enum_input("radio", $attrs, $field, ($value || isset($_GET["select"]) ? $value : ""), ($field["null"] ? "" : null))
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='orig' checked><i>" . lang('original') . "</i></label> " : "")
. enum_input("radio", $attrs, $field, $value, lang('empty'))
;
}
$options = $this->foreignKeyOptions($table, $field["field"], $value);