Merge pull request #1334 from nisargjhaveri/feature_857

feature 857: Regex search and replace
This commit is contained in:
Marc Delisle 2014-08-16 07:30:29 -04:00
commit 7be74bf634
4 changed files with 119 additions and 56 deletions

View File

@ -1362,40 +1362,81 @@ EOT;
}
}
$htmlOutput .= '</select>';
$htmlOutput .= '<br>' . PMA_Util::getCheckbox('useRegex' , __('Use regular expression'), false, false);
return $htmlOutput;
}
/**
* Returns HTML for previewing strings found and their replacements
* Finds and returns Regex pattern and their replacements
*
* @param int $columnIndex index of the column
* @param string $find string to find in the column
* @param string $replaceWith string to replace with
* @param string $charSet character set of the connection
*
* @return string HTML for previewing strings found and their replacements
* @return array Array containing original values, replcaed values and count
*/
function getReplacePreview($columnIndex, $find, $replaceWith, $charSet)
function _getRegexReplaceRows($columnIndex, $find, $replaceWith, $charSet)
{
$column = $this->_columnNames[$columnIndex];
$sql_query = "SELECT "
. PMA_Util::backquote($column) . ","
. " REPLACE("
. PMA_Util::backquote($column) . ", '" . $find . "', '" . $replaceWith
. "'),"
. " 1," // to add an extra column that will have replaced value
. " COUNT(*)"
. " FROM " . PMA_Util::backquote($this->_db)
. "." . PMA_Util::backquote($this->_table)
. " WHERE " . PMA_Util::backquote($column)
. " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
. " RLIKE '" . PMA_Util::sqlAddSlashes($find) . "' COLLATE " . $charSet . "_bin"; // here we
// change the collation of the 2nd operand to a case sensitive
// binary collation to make sure that the comparison is case sensitive
$sql_query .= " GROUP BY " . PMA_Util::backquote($column)
. " ORDER BY " . PMA_Util::backquote($column) . " ASC";
$resultSet = $GLOBALS['dbi']->query(
$sql_query, null, PMA_DatabaseInterface::QUERY_STORE
);
$result = $GLOBALS['dbi']->fetchResult($sql_query, 0);
if (is_array($result)) {
foreach ($result as $index=>$row) {
$result[$index][1] = preg_replace("/" . $find . "/" , $replaceWith, $row[0]);
}
}
return $result;
}
/**
* Returns HTML for previewing strings found and their replacements
*
* @param int $columnIndex index of the column
* @param string $find string to find in the column
* @param string $replaceWith string to replace with
* @param boolean $useRegex to use Regex replace or not
* @param string $charSet character set of the connection
*
* @return string HTML for previewing strings found and their replacements
*/
function getReplacePreview($columnIndex, $find, $replaceWith, $useRegex, $charSet)
{
$column = $this->_columnNames[$columnIndex];
if( $useRegex ) {
$result = $this->_getRegexReplaceRows($columnIndex, $find, $replaceWith, $charSet);
} else {
$sql_query = "SELECT "
. PMA_Util::backquote($column) . ","
. " REPLACE("
. PMA_Util::backquote($column) . ", '" . $find . "', '" . $replaceWith
. "'),"
. " COUNT(*)"
. " FROM " . PMA_Util::backquote($this->_db)
. "." . PMA_Util::backquote($this->_table)
. " WHERE " . PMA_Util::backquote($column)
. " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
// change the collation of the 2nd operand to a case sensitive
// binary collation to make sure that the comparison is case sensitive
$sql_query .= " GROUP BY " . PMA_Util::backquote($column)
. " ORDER BY " . PMA_Util::backquote($column) . " ASC";
$result = $GLOBALS['dbi']->fetchResult($sql_query, 0);
}
$htmlOutput = '<form method="post" action="tbl_find_replace.php"'
. ' name="previewForm" id="previewForm" class="ajax">';
@ -1404,9 +1445,11 @@ EOT;
$htmlOutput .= '<input type="hidden" name="columnIndex" value="'
. $columnIndex . '" />';
$htmlOutput .= '<input type="hidden" name="findString"'
. ' value="' . $find . '" />';
. ' value="' . htmlspecialchars($find) . '" />';
$htmlOutput .= '<input type="hidden" name="replaceWith"'
. ' value="' . $replaceWith . '" />';
. ' value="' . htmlspecialchars($replaceWith) . '" />';
$htmlOutput .= '<input type="hidden" name="useRegex"'
. ' value="' . $useRegex . '" />';
$htmlOutput .= '<fieldset id="fieldset_find_replace_preview">';
$htmlOutput .= '<legend>' . __('Find and replace - preview') . '</legend>';
@ -1420,18 +1463,20 @@ EOT;
$htmlOutput .= '<tbody>';
$odd = true;
while ($row = $GLOBALS['dbi']->fetchRow($resultSet)) {
$val = $row[0];
$replaced = $row[1];
$count = $row[2];
if (is_array($result)) {
foreach ($result as $row) {
$val = $row[0];
$replaced = $row[1];
$count = $row[2];
$htmlOutput .= '<tr class="' . ($odd ? 'odd' : 'even') . '">';
$htmlOutput .= '<td class="right">' . htmlspecialchars($count) . '</td>';
$htmlOutput .= '<td>' . htmlspecialchars($val) . '</td>';
$htmlOutput .= '<td>' . htmlspecialchars($replaced) . '</td>';
$htmlOutput .= '</tr>';
$htmlOutput .= '<tr class="' . ($odd ? 'odd' : 'even') . '">';
$htmlOutput .= '<td class="right">' . htmlspecialchars($count) . '</td>';
$htmlOutput .= '<td>' . htmlspecialchars($val) . '</td>';
$htmlOutput .= '<td>' . htmlspecialchars($replaced) . '</td>';
$htmlOutput .= '</tr>';
$odd = ! $odd;
$odd = ! $odd;
}
}
$htmlOutput .= '</tbody>';
$htmlOutput .= '</table>';
@ -1449,26 +1494,45 @@ EOT;
/**
* Replaces a given string in a column with a give replacement
*
* @param int $columnIndex index of the column
* @param string $find string to find in the column
* @param string $replaceWith string to replace with
* @param string $charSet character set of the connection
* @param int $columnIndex index of the column
* @param string $find string to find in the column
* @param string $replaceWith string to replace with
* @param boolean $useRegex to use Regex replace or not
* @param string $charSet character set of the connection
*
* @return void
*/
function replace($columnIndex, $find, $replaceWith, $charSet)
function replace($columnIndex, $find, $replaceWith, $useRegex, $charSet)
{
$column = $this->_columnNames[$columnIndex];
$sql_query = "UPDATE " . PMA_Util::backquote($this->_db)
. "." . PMA_Util::backquote($this->_table)
. " SET " . PMA_Util::backquote($column) . " ="
. " REPLACE("
. PMA_Util::backquote($column) . ", '" . $find . "', '" . $replaceWith
. "')"
. " WHERE " . PMA_Util::backquote($column)
. " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
// change the collation of the 2nd operand to a case sensitive
// binary collation to make sure that the comparison is case sensitive
if ($useRegex) {
$toReplace = $this->_getRegexReplaceRows($columnIndex, $find, $replaceWith, $charSet);
$sql_query = "UPDATE " . PMA_Util::backquote($this->_db)
. "." . PMA_Util::backquote($this->_table)
. " SET " . PMA_Util::backquote($column) . " = CASE";
if (is_array($toReplace)) {
foreach ($toReplace as $row) {
$sql_query .= "\n WHEN " . PMA_Util::backquote($column) . " = '" . PMA_Util::sqlAddSlashes($row[0]) . "' THEN '" . PMA_Util::sqlAddSlashes($row[1]) . "'";
}
}
$sql_query .= " END"
. " WHERE " . PMA_Util::backquote($column)
. " RLIKE '" . PMA_Util::sqlAddSlashes($find) . "' COLLATE " . $charSet . "_bin"; // here we
// change the collation of the 2nd operand to a case sensitive
// binary collation to make sure that the comparison is case sensitive
}
else {
$sql_query = "UPDATE " . PMA_Util::backquote($this->_db)
. "." . PMA_Util::backquote($this->_table)
. " SET " . PMA_Util::backquote($column) . " ="
. " REPLACE("
. PMA_Util::backquote($column) . ", '" . $find . "', '" . $replaceWith
. "')"
. " WHERE " . PMA_Util::backquote($column)
. " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
// change the collation of the 2nd operand to a case sensitive
// binary collation to make sure that the comparison is case sensitive
}
$GLOBALS['dbi']->query(
$sql_query, null, PMA_DatabaseInterface::QUERY_STORE
);

View File

@ -25,6 +25,7 @@ if (isset($_POST['find'])) {
$_POST['columnIndex'],
$_POST['find'],
$_POST['replaceWith'],
$_POST['useRegex'],
$connectionCharSet
);
$response->addJSON('preview', $preview);
@ -43,6 +44,7 @@ if (isset($_POST['replace'])) {
$_POST['columnIndex'],
$_POST['findString'],
$_POST['replaceWith'],
$_POST['useRegex'],
$connectionCharSet
);
$htmlOutput .= PMA_Util::getMessage(

View File

@ -74,6 +74,7 @@ class PMA_TableReplaceSearchTest extends PHPUnit_Framework_TestCase
$find = 'findValue';
$replaceWith = 'replaceWithValue';
$useRegex = false;
$charSet = 'charSetValue';
$expectedQuery = "SELECT `column1`, REPLACE(`column1`, '" . $find . "', '"
@ -82,20 +83,14 @@ class PMA_TableReplaceSearchTest extends PHPUnit_Framework_TestCase
. " `column1` ORDER BY `column1` ASC";
// set expectations
$dbi->expects($this->once())
->method('query')
->with($expectedQuery);
$dbi->expects($this->at(1))
->method('fetchRow')
->will($this->returnValue(array('val1', 'replace1', 5)));
$dbi->expects($this->at(2))
->method('fetchRow')
->will($this->returnValue(array('va<2', 'replac<2', 1)));
$dbi->expects($this->at(3))
->method('fetchRow')
->will($this->returnValue(false));
->method('fetchResult')
->will($this->returnValue(array(
array('val1', 'replace1', 5),
array('va<2', 'replac<2', 1)
)));
$GLOBALS['dbi'] = $dbi;
$ret = $this->_object->getReplacePreview(0, $find, $replaceWith, $charSet);
$ret = $this->_object->getReplacePreview(0, $find, $replaceWith, $useRegex, $charSet);
// assert whether hidden values are properly set
$this->assertContains(
@ -141,6 +136,7 @@ class PMA_TableReplaceSearchTest extends PHPUnit_Framework_TestCase
$find = 'findValue';
$replaceWith = 'replaceWithValue';
$useRegex = false;
$charSet = 'charSetValue';
$expectedQuery = "UPDATE `dbName`.`tableName`"
@ -153,7 +149,7 @@ class PMA_TableReplaceSearchTest extends PHPUnit_Framework_TestCase
->with($expectedQuery);
$GLOBALS['dbi'] = $dbi;
$this->_object->replace(0, $find, $replaceWith, $charSet);
$this->_object->replace(0, $find, $replaceWith, $useRegex, $charSet);
}
}
?>

View File

@ -239,8 +239,9 @@ class PMA_TableSearch_Test extends PHPUnit_Framework_TestCase
$columnIndex = 0;
$find = "Field";
$replaceWith = "Column";
$useRegex = false;
$charSet = "UTF-8";
$tableSearch->replace($columnIndex, $find, $replaceWith, $charSet);
$tableSearch->replace($columnIndex, $find, $replaceWith, $useRegex, $charSet);
$sql_query = $GLOBALS['sql_query'];
$result = "UPDATE `PMA`.`PMA_BookMark` SET `Field1` = "
@ -288,11 +289,9 @@ class PMA_TableSearch_Test extends PHPUnit_Framework_TestCase
$dbi = $GLOBALS['dbi'];
$dbi->expects($this->at(3))->method('fetchRow')
->will($this->returnValue($value));
$dbi->expects($this->at(4))->method('fetchRow')
->will($this->returnValue(false));
$dbi->expects($this->once())
->method('fetchResult')
->will($this->returnValue(array($value)));
$GLOBALS['dbi'] = $dbi;
@ -300,12 +299,14 @@ class PMA_TableSearch_Test extends PHPUnit_Framework_TestCase
$columnIndex = 0;
$find = "Field";
$replaceWith = "Column";
$useRegex = false;
$charSet = "UTF-8";
$html = $tableSearch->getReplacePreview(
$columnIndex,
$find,
$replaceWith,
$useRegex,
$charSet
);