PostgreSQL: Don't treat interval type as number (bug #474)

This commit is contained in:
Jakub Vrana 2018-02-06 12:17:01 +01:00
parent 11a7fc0277
commit 6cfb3676a7
8 changed files with 20 additions and 10 deletions

View file

@ -1071,7 +1071,7 @@ if (!defined("DRIVER")) {
"binary" => "md5/sha1", "binary" => "md5/sha1",
"date|time" => "now", "date|time" => "now",
), array( ), array(
"(^|[^o])int|float|double|decimal" => "+/-", // not point number_type() => "+/-",
"date" => "+ interval/- interval", "date" => "+ interval/- interval",
"time" => "addtime/subtime", "time" => "addtime/subtime",
"char|text" => "concat", "char|text" => "concat",

View file

@ -789,7 +789,7 @@ AND typelem = 0"
"char" => "md5", "char" => "md5",
"date|time" => "now", "date|time" => "now",
), array( ), array(
"int|numeric|real|money" => "+/-", number_type() => "+/-",
"date|time" => "+ interval/- interval", //! escape "date|time" => "+ interval/- interval", //! escape
"char|text" => "||", "char|text" => "||",
) )

View file

@ -543,7 +543,7 @@ class Adminer {
$cols = array(); $cols = array();
foreach ($fields as $name => $field) { foreach ($fields as $name => $field) {
$is_text = preg_match('~char|text|enum|set~', $field["type"]); $is_text = preg_match('~char|text|enum|set~', $field["type"]);
if ((is_numeric($val["val"]) || !preg_match('~(^|[^o])int|float|double|decimal|bit~', $field["type"])) if ((is_numeric($val["val"]) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
&& (!preg_match("~[\x80-\xFF]~", $val["val"]) || $is_text) && (!preg_match("~[\x80-\xFF]~", $val["val"]) || $is_text)
) { ) {
$name = idf_escape($name); $name = idf_escape($name);
@ -828,7 +828,7 @@ class Adminer {
foreach ($row as $key => $val) { foreach ($row as $key => $val) {
$field = $fields[$key]; $field = $fields[$key];
$row[$key] = ($val !== null $row[$key] = ($val !== null
? unconvert_field($field, preg_match('~(^|[^o])int|float|double|decimal~', $field["type"]) && $val != '' ? $val : q($val)) ? unconvert_field($field, preg_match('~' . number_type() . '~', $field["type"]) && $val != '' ? $val : q($val))
: "NULL" : "NULL"
); );
} }

View file

@ -155,7 +155,7 @@ echo optionlist(array_merge($extra_types, $structured_types), $type);
<?php echo script("mixin(qsl('select'), {onfocus: function () { lastType = selectValue(this); }, onchange: editingTypeChange});", ""); ?> <?php echo script("mixin(qsl('select'), {onfocus: function () { lastType = selectValue(this); }, onchange: editingTypeChange});", ""); ?>
<td><input name="<?php echo h($key); ?>[length]" value="<?php echo h($field["length"]); ?>" size="3"<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); ?> aria-labelledby="label-length"><?php echo script("mixin(qsl('input'), {onfocus: editingLengthFocus, oninput: editingLengthChange});", ""); ?><td class="options"><?php //! type="number" with enabled JavaScript <td><input name="<?php echo h($key); ?>[length]" value="<?php echo h($field["length"]); ?>" size="3"<?php echo (!$field["length"] && preg_match('~var(char|binary)$~', $type) ? " class='required'" : ""); ?> aria-labelledby="label-length"><?php echo script("mixin(qsl('input'), {onfocus: editingLengthFocus, oninput: editingLengthChange});", ""); ?><td class="options"><?php //! type="number" with enabled JavaScript
echo "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>'; echo "<select name='" . h($key) . "[collation]'" . (preg_match('~(char|text|enum|set)$~', $type) ? "" : " class='hidden'") . '><option value="">(' . lang('collation') . ')' . optionlist($collations, $field["collation"]) . '</select>';
echo ($unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match('~((^|[^o])int|float|double|decimal)$~', $type) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : ''); echo ($unsigned ? "<select name='" . h($key) . "[unsigned]'" . (!$type || preg_match('~' . number_type() . '~', $type) ? "" : " class='hidden'") . '><option>' . optionlist($unsigned, $field["unsigned"]) . '</select>' : '');
echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>' . optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), $field["on_update"]) . '</select>' : ''); echo (isset($field['on_update']) ? "<select name='" . h($key) . "[on_update]'" . (preg_match('~timestamp|datetime~', $type) ? "" : " class='hidden'") . '>' . optionlist(array("" => "(" . lang('ON UPDATE') . ")", "CURRENT_TIMESTAMP"), $field["on_update"]) . '</select>' : '');
echo ($foreign_keys ? "<select name='" . h($key) . "[on_delete]'" . (preg_match("~`~", $type) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $on_actions), $field["on_delete"]) . "</select> " : " "); // space for IE echo ($foreign_keys ? "<select name='" . h($key) . "[on_delete]'" . (preg_match("~`~", $type) ? "" : " class='hidden'") . "><option value=''>(" . lang('ON DELETE') . ")" . optionlist(explode("|", $on_actions), $field["on_delete"]) . "</select> " : " "); // space for IE
} }
@ -181,7 +181,7 @@ function process_type($field, $collate = "COLLATE") {
global $unsigned; global $unsigned;
return " $field[type]" return " $field[type]"
. process_length($field["length"]) . process_length($field["length"])
. (preg_match('~(^|[^o])int|float|double|decimal~', $field["type"]) && in_array($field["unsigned"], $unsigned) ? " $field[unsigned]" : "") . (preg_match('~' . number_type() . '~', $field["type"]) && in_array($field["unsigned"], $unsigned) ? " $field[unsigned]" : "")
. (preg_match('~char|text|enum|set~', $field["type"]) && $field["collation"] ? " $collate " . q($field["collation"]) : "") . (preg_match('~char|text|enum|set~', $field["type"]) && $field["collation"] ? " $collate " . q($field["collation"]) : "")
; ;
} }

View file

@ -41,6 +41,13 @@ function number($val) {
return preg_replace('~[^0-9]+~', '', $val); return preg_replace('~[^0-9]+~', '', $val);
} }
/** Get regular expression to match numeric types
* @return string
*/
function number_type() {
return '(?<!o)int(?!er)|numeric|real|float|double|decimal|money'; // not point, not interval
}
/** Disable magic_quotes_gpc /** Disable magic_quotes_gpc
* @param array e.g. (&$_GET, &$_POST, &$_COOKIE) * @param array e.g. (&$_GET, &$_POST, &$_COOKIE)
* @param bool whether to leave values as is * @param bool whether to leave values as is
@ -970,7 +977,7 @@ function input($field, $value, $function) {
} }
// type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator // type='date' and type='time' display localized value which may be confusing, type='datetime' uses 'T' as date and time separator
echo "<input" echo "<input"
. ((!$has_function || $function === "") && preg_match('~(?<!o)int~', $field["type"]) && !preg_match('~\[\]~', $field["full_type"]) ? " type='number'" : "") . ((!$has_function || $function === "") && preg_match('~(?<!o)int(?!er)~', $field["type"]) && !preg_match('~\[\]~', $field["full_type"]) ? " type='number'" : "")
. " value='" . h($value) . "'" . ($maxlength ? " data-maxlength='$maxlength'" : "") . " value='" . h($value) . "'" . ($maxlength ? " data-maxlength='$maxlength'" : "")
. (preg_match('~char|binary~', $field["type"]) && $maxlength > 20 ? " size='40'" : "") . (preg_match('~char|binary~', $field["type"]) && $maxlength > 20 ? " size='40'" : "")
. "$attrs>" . "$attrs>"

View file

@ -316,7 +316,7 @@ function editingTypeChange() {
alterClass(el, 'hidden', !/(char|text|enum|set)$/.test(text)); alterClass(el, 'hidden', !/(char|text|enum|set)$/.test(text));
} }
if (el.name == name + '[unsigned]') { if (el.name == name + '[unsigned]') {
alterClass(el, 'hidden', !/((^|[^o])int|float|double|decimal)$/.test(text)); alterClass(el, 'hidden', !/(^|[^o])int(?!er)|numeric|real|float|double|decimal|money/.test(text));
} }
if (el.name == name + '[on_update]') { if (el.name == name + '[on_update]') {
alterClass(el, 'hidden', !/timestamp|datetime/.test(text)); // MySQL supports datetime since 5.6.5 alterClass(el, 'hidden', !/timestamp|datetime/.test(text)); // MySQL supports datetime since 5.6.5

View file

@ -1,3 +1,6 @@
Adminer 4.6.1-dev:
PostgreSQL: Don't treat interval type as number (bug #474)
Adminer 4.6.0 (released 2018-02-05): Adminer 4.6.0 (released 2018-02-05):
Fix counting selected rows after going back to select page Fix counting selected rows after going back to select page
PHP <5.3 compatibility even with Elasticsearch enabled PHP <5.3 compatibility even with Elasticsearch enabled

View file

@ -197,7 +197,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
if ($link) { if ($link) {
$return = "<a href='$link'" . (is_url($link) ? target_blank() : "") . ">$return</a>"; $return = "<a href='$link'" . (is_url($link) ? target_blank() : "") . ">$return</a>";
} }
if (!$link && !like_bool($field) && preg_match('~int|float|double|decimal~', $field["type"])) { if (!$link && !like_bool($field) && preg_match('~' . number_type() . '~', $field["type"])) {
$return = "<div class='number'>$return</div>"; // Firefox doesn't support <colgroup> $return = "<div class='number'>$return</div>"; // Firefox doesn't support <colgroup>
} elseif (preg_match('~date~', $field["type"])) { } elseif (preg_match('~date~', $field["type"])) {
$return = "<div class='datetime'>$return</div>"; $return = "<div class='datetime'>$return</div>";
@ -342,7 +342,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
if (($key < 0 ? "" : $col) . $val != "") { if (($key < 0 ? "" : $col) . $val != "") {
$conds = array(); $conds = array();
foreach (($col != "" ? array($col => $fields[$col]) : $fields) as $name => $field) { foreach (($col != "" ? array($col => $fields[$col]) : $fields) as $name => $field) {
if ($col != "" || is_numeric($val) || !preg_match('~int|float|double|decimal~', $field["type"])) { if ($col != "" || is_numeric($val) || !preg_match('~' . number_type() . '~', $field["type"])) {
$name = idf_escape($name); $name = idf_escape($name);
if ($col != "" && $field["type"] == "enum") { if ($col != "" && $field["type"] == "enum") {
$conds[] = (in_array(0, $val) ? "$name IS NULL OR " : "") . "$name IN (" . implode(", ", array_map('intval', $val)) . ")"; $conds[] = (in_array(0, $val) ? "$name IS NULL OR " : "") . "$name IN (" . implode(", ", array_map('intval', $val)) . ")";