diff --git a/ChangeLog b/ChangeLog index e1ee08e2e..c9acc6b82 100644 --- a/ChangeLog +++ b/ChangeLog @@ -62,6 +62,7 @@ danbarry (todo: Documentation.html, improve code formatting) + rfe #1962383 [designer] Option to create a PDF page - patch #2007196, Typos in comments, thanks to knittl - knittl +- bug #1982315 [GUI] Comma and quote in ENUM, thanks to Joshua Hogendorn 2.11.8.0 (not yet released) - patch #1987593 [interface] Table list pagination in navi, diff --git a/libraries/common.lib.php b/libraries/common.lib.php index d1ef9e87b..0a64bb383 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -1422,28 +1422,6 @@ function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false) return $sign . $value . ' ' . $unit; } // end of the 'PMA_formatNumber' function -/** - * Extracts ENUM / SET options from a type definition string - * - * @param string The column type definition - * - * @return array The options or - * boolean false in case of an error. - * - * @author rabus - */ -function PMA_getEnumSetOptions($type_def) -{ - $open = strpos($type_def, '('); - $close = strrpos($type_def, ')'); - if (!$open || !$close) { - return false; - } - $options = substr($type_def, $open + 2, $close - $open - 3); - $options = explode('\',\'', $options); - return $options; -} // end of the 'PMA_getEnumSetOptions' function - /** * Writes localised date * @@ -2479,26 +2457,83 @@ function PMA_printable_bit_value($value, $length) { } /** - * Extracts the true field type and length from a field type spec + * Extracts the various parts from a field type spec * * @uses strpos() * @uses chop() * @uses substr() * @param string $fieldspec - * @return array associative array containing the type and length + * @return array associative array containing type, spec_in_brackets + * and possibly enum_set_values (another array) + * @author Marc Delisle + * @author Joshua Hogendorn */ -function PMA_extract_type_length($fieldspec) { +function PMA_extractFieldSpec($fieldspec) { $first_bracket_pos = strpos($fieldspec, '('); if ($first_bracket_pos) { - $length = chop(substr($fieldspec, $first_bracket_pos + 1, (strpos($fieldspec, ')') - $first_bracket_pos - 1))); - $type = chop(substr($fieldspec, 0, $first_bracket_pos)); + $spec_in_brackets = chop(substr($fieldspec, $first_bracket_pos + 1, (strpos($fieldspec, ')') - $first_bracket_pos - 1))); + // convert to lowercase just to be sure + $type = strtolower(chop(substr($fieldspec, 0, $first_bracket_pos))); } else { $type = $fieldspec; - $length = ''; + $spec_in_brackets = ''; } + + if ('enum' == $type || 'set' == $type) { + // Define our working vars + $enum_set_values = array(); + $working = ""; + $in_string = false; + $index = 0; + + // While there is another character to process + while (isset($fieldspec[$index])) { + // Grab the char to look at + $char = $fieldspec[$index]; + + // If it is a single quote, needs to be handled specially + if ($char == "'") { + // If we are not currently in a string, begin one + if (! $in_string) { + $in_string = true; + $working = ""; + // Otherwise, it may be either an end of a string, or a 'double quote' which can be handled as-is + } else { + // Check out the next character (if possible) + $has_next = isset($fieldspec[$index + 1]); + $next = $has_next ? $fieldspec[$index + 1] : null; + + // If we have reached the end of our 'working' string (because there are no more chars, or the next char is not another quote) + if (! $has_next || $next != "'") { + $enum_set_values[] = $working; + $in_string = false; + + // Otherwise, this is a 'double quote', and can be added to the working string + } elseif ($next == "'") { + $working .= "'"; + // Skip the next char; we already know what it is + $index++; + } + } + // escaping of a quote? + } elseif ('\\' == $char && isset($fieldspec[$index + 1]) && "'" == $fieldspec[$index + 1]) { + $working .= "'"; + $index++; + // Otherwise, add it to our working string like normal + } else { + $working .= $char; + } + // Increment character index + $index++; + } // end while + } else { + $enum_set_values = array(); + } + return array( 'type' => $type, - 'length' => $length + 'spec_in_brackets' => $spec_in_brackets, + 'enum_set_values' => $enum_set_values ); } diff --git a/libraries/tbl_properties.inc.php b/libraries/tbl_properties.inc.php index 1b4ab84e3..0f7550837 100644 --- a/libraries/tbl_properties.inc.php +++ b/libraries/tbl_properties.inc.php @@ -231,9 +231,9 @@ for ($i = 0; $i < $num_fields; $i++) { } if (isset($row['Type'])) { - $type_and_length = PMA_extract_type_length($row['Type']); - if ($type_and_length['type'] == 'bit') { - $row['Default'] = PMA_printable_bit_value($row['Default'], $type_and_length['length']); + $extracted_fieldspec = PMA_extractFieldSpec($row['Type']); + if ($extracted_fieldspec['type'] == 'bit') { + $row['Default'] = PMA_printable_bit_value($row['Default'], $extracted_fieldspec['spec_in_brackets']); } } // Cell index: If certain fields get left out, the counter shouldn't change. @@ -267,27 +267,29 @@ for ($i = 0; $i < $num_fields; $i++) { .' id="field_' . $i . '_' . ($ci - $ci_offset) . '" >'; if (empty($row['Type'])) { + // creating a column $row['Type'] = ''; $type = ''; } else { $type = $row['Type']; } - // set or enum types: slashes single quotes inside options - if (preg_match('@^(set|enum)\((.+)\)$@i', $type, $tmp)) { - $type = $tmp[1]; - $length = substr(preg_replace('@([^,])\'\'@', '\\1\\\'', ',' . $tmp[2]), 1); - } else { - // strip the "BINARY" attribute, except if we find "BINARY(" because - // this would be a BINARY or VARBINARY field type - $type = preg_replace('@BINARY([^\(])@i', '', $type); - $type = preg_replace('@ZEROFILL@i', '', $type); - $type = preg_replace('@UNSIGNED@i', '', $type); - $type_and_length = PMA_extract_type_length($type); - $type = $type_and_length['type']; - $length = $type_and_length['length']; - unset($type_and_length); - } // end if else + if (! empty($row['Type'])) { + $type = $extracted_fieldspec['type']; + if ('set' == $extracted_fieldspec['type'] || 'enum' == $extracted_fieldspec['type']) { + $length = $extracted_fieldspec['spec_in_brackets']; + } else { + // strip the "BINARY" attribute, except if we find "BINARY(" because + // this would be a BINARY or VARBINARY field type + $type = preg_replace('@BINARY([^\(])@i', '', $type); + $type = preg_replace('@ZEROFILL@i', '', $type); + $type = preg_replace('@UNSIGNED@i', '', $type); + $length = $extracted_fieldspec['spec_in_brackets']; + } // end if else + } else { + // creating a column + $length = ''; + } // some types, for example longtext, are reported as // "longtext character set latin7" when their charset and / or collation @@ -335,7 +337,7 @@ for ($i = 0; $i < $num_fields; $i++) { } // column length - if (preg_match('@^(set|enum)$@i', $type)) { + if (isset($extracted_fieldspec) && ('set' == $extracted_fieldspec['type'] || 'enum' == $extracted_fieldspec['type'])) { $binary = 0; $unsigned = 0; $zerofill = 0; diff --git a/tbl_change.php b/tbl_change.php index a5d2e7c95..10cadaeb8 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -312,6 +312,7 @@ foreach ($rows as $row_id => $vrow) { if (! isset($table_fields[$i]['processed'])) { $table_fields[$i]['Field_html'] = htmlspecialchars($table_fields[$i]['Field']); $table_fields[$i]['Field_md5'] = md5($table_fields[$i]['Field']); + // True_Type contains only the type (stops at first bracket) $table_fields[$i]['True_Type'] = preg_replace('@\(.*@s', '', $table_fields[$i]['Type']); // d a t e t i m e @@ -379,7 +380,7 @@ foreach ($rows as $row_id => $vrow) { } } $field = $table_fields[$i]; - $type_and_length = PMA_extract_type_length($field['Type']); + $extracted_fieldspec = PMA_extractFieldSpec($field['Type']); if (-1 === $field['len']) { $field['len'] = PMA_DBI_field_len($vresult, $i); @@ -421,7 +422,7 @@ foreach ($rows as $row_id => $vrow) { $special_chars = ''; $data = $vrow[$field['Field']]; } elseif ($field['True_Type'] == 'bit') { - $special_chars = PMA_printable_bit_value($vrow[$field], $type_and_length['length']); + $special_chars = PMA_printable_bit_value($vrow[$field], $extracted_fieldspec['spec_in_brackets']); } else { // loic1: special binary "characters" if ($field['is_binary'] || $field['is_blob']) { @@ -447,7 +448,7 @@ foreach ($rows as $row_id => $vrow) { $data = $field['Default']; } if ($field['True_Type'] == 'bit') { - $special_chars = PMA_printable_bit_value($field['Default'], $type_and_length['length']); + $special_chars = PMA_printable_bit_value($field['Default'], $extracted_fieldspec['spec_in_brackets']); } else { $special_chars = htmlspecialchars($field['Default']); } @@ -678,7 +679,7 @@ foreach ($rows as $row_id => $vrow) { } elseif ($field['pma_type'] == 'enum') { if (! isset($table_fields[$i]['values'])) { $table_fields[$i]['values'] = array(); - foreach (PMA_getEnumSetOptions($field['Type']) as $val) { + foreach ($extracted_fieldspec['enum_set_values'] as $val) { // Removes automatic MySQL escape format $val = str_replace('\'\'', '\'', str_replace('\\\\', '\\', $val)); $table_fields[$i]['values'][] = array( @@ -749,7 +750,7 @@ foreach ($rows as $row_id => $vrow) { } elseif ($field['pma_type'] == 'set') { if (! isset($table_fields[$i]['values'])) { $table_fields[$i]['values'] = array(); - foreach (PMA_getEnumSetOptions($field['Type']) as $val) { + foreach ($extracted_fieldspec['enum_set_values'] as $val) { $table_fields[$i]['values'][] = array( 'plain' => $val, 'html' => htmlspecialchars($val), diff --git a/tbl_structure.php b/tbl_structure.php index 36c7fa309..82b20761d 100644 --- a/tbl_structure.php +++ b/tbl_structure.php @@ -212,13 +212,10 @@ while ($row = PMA_DBI_fetch_assoc($fields_rs)) { $aryFields[] = $row['Field']; $type = $row['Type']; - $type_and_length = PMA_extract_type_length($row['Type']); + $extracted_fieldspec = PMA_extractFieldSpec($row['Type']); - // reformat mysql query output - staybyte - 9. June 2001 - // loic1: set or enum types: slashes single quotes inside options - if (preg_match('@^(set|enum)\((.+)\)$@i', $type, $tmp)) { - $tmp[2] = substr(preg_replace('@([^,])\'\'@', '\\1\\\'', ',' . $tmp[2]), 1); - $type = $tmp[1] . '(' . str_replace(',', ', ', $tmp[2]) . ')'; + if ('set' == $extracted_fieldspec['type'] || 'enum' == $extracted_fieldspec['type']) { + $type = $extracted_fieldspec['type'] . '(' . $extracted_fieldspec['spec_in_brackets'] . ')'; // for the case ENUM('–','“') $type = htmlspecialchars($type); @@ -339,8 +336,8 @@ while ($row = PMA_DBI_fetch_assoc($fields_rs)) {