Merge pull request #18872 from kamil-tekiela/Refactor-Indexes-doSaveData
New implementation for Indexes
This commit is contained in:
commit
ac0e478057
@ -193,7 +193,7 @@ return [
|
||||
],
|
||||
'table_indexes' => [
|
||||
'class' => Indexes::class,
|
||||
'arguments' => ['$response' => '@response', '$template' => '@template', '$dbi' => '@dbi'],
|
||||
'arguments' => ['$dbi' => '@dbi'],
|
||||
],
|
||||
'table_maintenance' => ['class' => PhpMyAdmin\Table\Maintenance::class, 'arguments' => ['$dbi' => '@dbi']],
|
||||
'table_search' => ['class' => Search::class, 'arguments' => ['$dbi' => '@dbi']],
|
||||
|
||||
@ -4926,12 +4926,12 @@ parameters:
|
||||
path: src/Controllers/Table/IndexRenameController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$params of static method PhpMyAdmin\\\\Url\\:\\:getCommon\\(\\) expects array\\<string, bool\\|int\\|string\\>, mixed given\\.$#"
|
||||
message: "#^Parameter \\#1 \\$oldIndexName of method PhpMyAdmin\\\\Table\\\\Indexes\\:\\:getSqlQueryForRename\\(\\) expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Controllers/Table/IndexRenameController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#7 \\$oldIndexName of method PhpMyAdmin\\\\Table\\\\Indexes\\:\\:doSaveData\\(\\) expects string, mixed given\\.$#"
|
||||
message: "#^Parameter \\#1 \\$params of static method PhpMyAdmin\\\\Url\\:\\:getCommon\\(\\) expects array\\<string, bool\\|int\\|string\\>, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Controllers/Table/IndexRenameController.php
|
||||
|
||||
@ -4955,6 +4955,11 @@ parameters:
|
||||
count: 1
|
||||
path: src/Controllers/Table/IndexesController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$oldIndexName of method PhpMyAdmin\\\\Table\\\\Indexes\\:\\:getSqlQueryForIndexCreateOrEdit\\(\\) expects string\\|null, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Controllers/Table/IndexesController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$params of static method PhpMyAdmin\\\\Url\\:\\:getCommon\\(\\) expects array\\<string, bool\\|int\\|string\\>, mixed given\\.$#"
|
||||
count: 1
|
||||
@ -15165,6 +15170,11 @@ parameters:
|
||||
count: 1
|
||||
path: src/Table/Indexes.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a negated boolean, int\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Table/Indexes.php
|
||||
|
||||
-
|
||||
message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#"
|
||||
count: 2
|
||||
@ -15367,7 +15377,7 @@ parameters:
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 18
|
||||
count: 17
|
||||
path: src/Table/Table.php
|
||||
|
||||
-
|
||||
@ -15437,7 +15447,7 @@ parameters:
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a negated boolean, int\\|null given\\.$#"
|
||||
count: 2
|
||||
count: 1
|
||||
path: src/Table/Table.php
|
||||
|
||||
-
|
||||
@ -15477,7 +15487,7 @@ parameters:
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$identifier of static method PhpMyAdmin\\\\Util\\:\\:backquote\\(\\) expects string\\|Stringable\\|null, mixed given\\.$#"
|
||||
count: 7
|
||||
count: 6
|
||||
path: src/Table/Table.php
|
||||
|
||||
-
|
||||
@ -17895,26 +17905,6 @@ parameters:
|
||||
count: 1
|
||||
path: tests/classes/Stubs/ResponseRenderer.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method PhpMyAdmin\\\\DatabaseInterface\\:\\:expects\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: tests/classes/Table/IndexesTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method method\\(\\) on mixed\\.$#"
|
||||
count: 1
|
||||
path: tests/classes/Table/IndexesTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method willReturn\\(\\) on mixed\\.$#"
|
||||
count: 1
|
||||
path: tests/classes/Table/IndexesTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$haystack of method PHPUnit\\\\Framework\\\\Assert\\:\\:assertStringContainsString\\(\\) expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: tests/classes/Table/IndexesTest.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method PhpMyAdmin\\\\DatabaseInterface\\:\\:expects\\(\\)\\.$#"
|
||||
count: 4
|
||||
@ -17925,11 +17915,6 @@ parameters:
|
||||
count: 1
|
||||
path: tests/classes/Table/TableTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'Key_name' on mixed\\.$#"
|
||||
count: 1
|
||||
path: tests/classes/Table/TableTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'SCHEMA_TABLES' on mixed\\.$#"
|
||||
count: 1
|
||||
|
||||
@ -3568,20 +3568,15 @@
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
</InvalidArrayOffset>
|
||||
<MixedArgument>
|
||||
<code>$indexName</code>
|
||||
<code>$indexName</code>
|
||||
<code>$oldIndexName</code>
|
||||
</MixedArgument>
|
||||
<MixedAssignment>
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
<code>$indexName</code>
|
||||
<code>$oldIndexName</code>
|
||||
</MixedAssignment>
|
||||
<PossiblyInvalidArgument>
|
||||
<code><![CDATA[$_POST['index']['Key_name']]]></code>
|
||||
<code>$oldIndex</code>
|
||||
</PossiblyInvalidArgument>
|
||||
<PossiblyInvalidCast>
|
||||
<code><![CDATA[$_POST['index']['Key_name']]]></code>
|
||||
<code>$oldIndex</code>
|
||||
</PossiblyInvalidCast>
|
||||
</file>
|
||||
<file src="src/Controllers/Table/IndexesController.php">
|
||||
<DeprecatedMethod>
|
||||
@ -3601,6 +3596,7 @@
|
||||
</MixedAssignment>
|
||||
<PossiblyInvalidArgument>
|
||||
<code><![CDATA[$_POST['columns']]]></code>
|
||||
<code>$oldIndex</code>
|
||||
</PossiblyInvalidArgument>
|
||||
<PossiblyInvalidArrayOffset>
|
||||
<code><![CDATA[$_POST['index']['Index_choice']]]></code>
|
||||
@ -11466,6 +11462,11 @@
|
||||
<code><![CDATA[$columnMeta['DefaultValue']]]></code>
|
||||
</PossiblyUndefinedArrayOffset>
|
||||
</file>
|
||||
<file src="src/Table/Indexes.php">
|
||||
<PossiblyNullOperand>
|
||||
<code><![CDATA[$column->getSubPart()]]></code>
|
||||
</PossiblyNullOperand>
|
||||
</file>
|
||||
<file src="src/Table/Search.php">
|
||||
<MixedArgument>
|
||||
<code><![CDATA[$_POST['criteriaColumnNames'][$columnIndex]]]></code>
|
||||
@ -11736,7 +11737,6 @@
|
||||
<PossiblyInvalidArgument>
|
||||
<code><![CDATA[$_POST['constraint_name'][$masterFieldMd5]]]></code>
|
||||
<code><![CDATA[$fields[$column]['expr']]]></code>
|
||||
<code>$oldIndex</code>
|
||||
<code><![CDATA[$options['expr']]]></code>
|
||||
</PossiblyInvalidArgument>
|
||||
<PossiblyInvalidArrayOffset>
|
||||
@ -11776,7 +11776,6 @@
|
||||
<code><![CDATA[$statement->altered]]></code>
|
||||
</PossiblyNullIterator>
|
||||
<PossiblyNullOperand>
|
||||
<code><![CDATA[$column->getSubPart()]]></code>
|
||||
<code><![CDATA[Generator::mysqlDie($tmpErrorCreate, $createQuery, false, '', false)]]></code>
|
||||
<code><![CDATA[Generator::mysqlDie($tmpErrorDrop, $dropQuery, false, '', false)]]></code>
|
||||
</PossiblyNullOperand>
|
||||
@ -11787,9 +11786,6 @@
|
||||
<PossiblyUnusedReturnValue>
|
||||
<code>true|Message</code>
|
||||
</PossiblyUnusedReturnValue>
|
||||
<ReferenceConstraintViolation>
|
||||
<code>return $sqlQuery;</code>
|
||||
</ReferenceConstraintViolation>
|
||||
<UnsupportedPropertyReferenceUsage>
|
||||
<code><![CDATA[$this->uiprefs =& $_SESSION['tmpval']['table_uiprefs'][$serverId][$this->dbName][$this->name]]]></code>
|
||||
</UnsupportedPropertyReferenceUsage>
|
||||
@ -15256,6 +15252,9 @@
|
||||
<MixedAssignment>
|
||||
<code>$value</code>
|
||||
</MixedAssignment>
|
||||
<PossiblyUnusedMethod>
|
||||
<code>clear</code>
|
||||
</PossiblyUnusedMethod>
|
||||
</file>
|
||||
<file src="tests/classes/SystemDatabaseTest.php">
|
||||
<DeprecatedMethod>
|
||||
@ -15270,22 +15269,6 @@
|
||||
<code>providerColumnMetaDefault</code>
|
||||
</PossiblyUnusedMethod>
|
||||
</file>
|
||||
<file src="tests/classes/Table/IndexesTest.php">
|
||||
<DeprecatedMethod>
|
||||
<code>Config::getInstance()</code>
|
||||
<code>DatabaseInterface::getInstance()</code>
|
||||
</DeprecatedMethod>
|
||||
<MixedArgument>
|
||||
<code><![CDATA[$jsonArray['sql_data']]]></code>
|
||||
</MixedArgument>
|
||||
<MixedMethodCall>
|
||||
<code>method</code>
|
||||
<code>willReturn</code>
|
||||
</MixedMethodCall>
|
||||
<UndefinedMethod>
|
||||
<code>expects</code>
|
||||
</UndefinedMethod>
|
||||
</file>
|
||||
<file src="tests/classes/Table/Maintenance/MessageTest.php">
|
||||
<PossiblyUnusedMethod>
|
||||
<code>providerForTestFromArray</code>
|
||||
@ -15319,8 +15302,6 @@
|
||||
<code>DatabaseInterface::getInstance()</code>
|
||||
<code>DatabaseInterface::getInstance()</code>
|
||||
<code>DatabaseInterface::getInstance()</code>
|
||||
<code>DatabaseInterface::getInstance()</code>
|
||||
<code>DatabaseInterface::getInstance()</code>
|
||||
</DeprecatedMethod>
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['sql_drop_table']]]></code>
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
</div>
|
||||
|
||||
<input type="text"
|
||||
name="index[Key_name]"
|
||||
name="index"
|
||||
id="input_index_name"
|
||||
size="25"
|
||||
maxlength="64"
|
||||
|
||||
@ -9,6 +9,7 @@ use PhpMyAdmin\Controllers\AbstractController;
|
||||
use PhpMyAdmin\Current;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\DbTableExists;
|
||||
use PhpMyAdmin\Html\Generator;
|
||||
use PhpMyAdmin\Http\ServerRequest;
|
||||
use PhpMyAdmin\Identifiers\DatabaseName;
|
||||
use PhpMyAdmin\Identifiers\TableName;
|
||||
@ -21,7 +22,6 @@ use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
use function is_array;
|
||||
|
||||
final class IndexRenameController extends AbstractController
|
||||
{
|
||||
@ -40,95 +40,110 @@ final class IndexRenameController extends AbstractController
|
||||
$GLOBALS['urlParams'] ??= null;
|
||||
$GLOBALS['errorUrl'] ??= null;
|
||||
|
||||
if (! isset($_POST['create_edit_table'])) {
|
||||
if (! $this->checkParameters(['db', 'table'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$GLOBALS['urlParams'] = ['db' => Current::$database, 'table' => Current::$table];
|
||||
$GLOBALS['errorUrl'] = Util::getScriptNameForOption(
|
||||
Config::getInstance()->settings['DefaultTabTable'],
|
||||
'table',
|
||||
);
|
||||
$GLOBALS['errorUrl'] .= Url::getCommon($GLOBALS['urlParams'], '&');
|
||||
|
||||
$databaseName = DatabaseName::tryFrom($request->getParam('db'));
|
||||
if ($databaseName === null || ! $this->dbTableExists->selectDatabase($databaseName)) {
|
||||
if ($request->isAjax()) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', Message::error(__('No databases selected.')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->redirect('/', ['reload' => true, 'message' => __('No databases selected.')]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$tableName = TableName::tryFrom($request->getParam('table'));
|
||||
if ($tableName === null || ! $this->dbTableExists->hasTable($databaseName, $tableName)) {
|
||||
if ($request->isAjax()) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', Message::error(__('No table selected.')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->redirect('/', ['reload' => true, 'message' => __('No table selected.')]);
|
||||
|
||||
return;
|
||||
}
|
||||
if (! $this->checkParameters(['db', 'table'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($_POST['index'])) {
|
||||
if (is_array($_POST['index'])) {
|
||||
// coming already from form
|
||||
$oldIndex = is_array($_POST['old_index']) ? $_POST['old_index']['Key_name'] : $_POST['old_index'];
|
||||
$index = clone $this->dbi->getTable(Current::$database, Current::$table)->getIndex($oldIndex);
|
||||
$index->setName($_POST['index']['Key_name']);
|
||||
} else {
|
||||
$index = $this->dbi->getTable(Current::$database, Current::$table)->getIndex($_POST['index']);
|
||||
$GLOBALS['urlParams'] = ['db' => Current::$database, 'table' => Current::$table];
|
||||
$GLOBALS['errorUrl'] = Util::getScriptNameForOption(
|
||||
Config::getInstance()->settings['DefaultTabTable'],
|
||||
'table',
|
||||
);
|
||||
$GLOBALS['errorUrl'] .= Url::getCommon($GLOBALS['urlParams'], '&');
|
||||
|
||||
$databaseName = DatabaseName::tryFrom($request->getParam('db'));
|
||||
if ($databaseName === null || ! $this->dbTableExists->selectDatabase($databaseName)) {
|
||||
if ($request->isAjax()) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', Message::error(__('No databases selected.')));
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$index = new Index();
|
||||
|
||||
$this->redirect('/', ['reload' => true, 'message' => __('No databases selected.')]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($_POST['do_save_data'])) {
|
||||
$oldIndexName = $request->getParsedBodyParam('old_index', '');
|
||||
$this->indexes->doSaveData(
|
||||
$request,
|
||||
$index,
|
||||
true,
|
||||
Current::$database,
|
||||
Current::$table,
|
||||
$request->hasBodyParam('preview_sql'),
|
||||
$oldIndexName,
|
||||
$tableName = TableName::tryFrom($request->getParam('table'));
|
||||
if ($tableName === null || ! $this->dbTableExists->hasTable($databaseName, $tableName)) {
|
||||
if ($request->isAjax()) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', Message::error(__('No table selected.')));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->redirect('/', ['reload' => true, 'message' => __('No table selected.')]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$oldIndexName = $request->getParsedBodyParam('old_index');
|
||||
$indexName = $request->getParsedBodyParam('index');
|
||||
if ($oldIndexName === null) {
|
||||
$index = $this->dbi->getTable($databaseName->getName(), $tableName->getName())->getIndex($indexName);
|
||||
|
||||
$formParams = [
|
||||
'db' => $databaseName->getName(),
|
||||
'table' => $tableName->getName(),
|
||||
'old_index' => $index->getName(),
|
||||
];
|
||||
|
||||
$this->render('table/index_rename_form', ['index' => $index, 'form_params' => $formParams]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// coming already from form
|
||||
$index = $this->dbi->getTable($databaseName->getName(), $tableName->getName())->getIndex($oldIndexName);
|
||||
$index->setName($indexName);
|
||||
|
||||
$previewSql = $request->hasBodyParam('preview_sql');
|
||||
|
||||
$sqlQuery = $this->indexes->getSqlQueryForRename(
|
||||
$oldIndexName,
|
||||
$index,
|
||||
$databaseName->getName(),
|
||||
$tableName->getName(),
|
||||
);
|
||||
|
||||
if ($previewSql) {
|
||||
$this->response->addJSON(
|
||||
'sql_data',
|
||||
$this->template->render('preview_sql', ['query_data' => $sqlQuery]),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->displayRenameForm($index);
|
||||
}
|
||||
$logicError = $this->indexes->getError();
|
||||
if ($logicError instanceof Message) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', $logicError);
|
||||
|
||||
/**
|
||||
* Display the rename form to rename an index
|
||||
*
|
||||
* @param Index $index An Index instance.
|
||||
*/
|
||||
private function displayRenameForm(Index $index): void
|
||||
{
|
||||
$this->dbi->selectDb(Current::$database);
|
||||
|
||||
$formParams = ['db' => Current::$database, 'table' => Current::$table];
|
||||
|
||||
if (isset($_POST['old_index'])) {
|
||||
$formParams['old_index'] = $_POST['old_index'];
|
||||
} elseif (isset($_POST['index'])) {
|
||||
$formParams['old_index'] = $_POST['index'];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->render('table/index_rename_form', ['index' => $index, 'form_params' => $formParams]);
|
||||
$this->dbi->query($sqlQuery);
|
||||
|
||||
$message = Message::success(__('Table %1$s has been altered successfully.'));
|
||||
$message->addParam($tableName->getName());
|
||||
$this->response->addJSON(
|
||||
'message',
|
||||
Generator::getMessage($message, $sqlQuery, 'success'),
|
||||
);
|
||||
|
||||
$indexes = Index::getFromTable($this->dbi, $tableName->getName(), $databaseName->getName());
|
||||
$indexesDuplicates = Index::findDuplicates($tableName->getName(), $databaseName->getName());
|
||||
|
||||
$this->response->addJSON(
|
||||
'index_table',
|
||||
$this->template->render('indexes', [
|
||||
'url_params' => ['db' => $databaseName->getName(), 'table' => $tableName->getName()],
|
||||
'indexes' => $indexes,
|
||||
'indexes_duplicates' => $indexesDuplicates,
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,10 +5,12 @@ declare(strict_types=1);
|
||||
namespace PhpMyAdmin\Controllers\Table;
|
||||
|
||||
use PhpMyAdmin\Config;
|
||||
use PhpMyAdmin\Container\ContainerBuilder;
|
||||
use PhpMyAdmin\Controllers\AbstractController;
|
||||
use PhpMyAdmin\Current;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\DbTableExists;
|
||||
use PhpMyAdmin\Html\Generator;
|
||||
use PhpMyAdmin\Http\ServerRequest;
|
||||
use PhpMyAdmin\Identifiers\DatabaseName;
|
||||
use PhpMyAdmin\Identifiers\TableName;
|
||||
@ -100,15 +102,69 @@ class IndexesController extends AbstractController
|
||||
}
|
||||
|
||||
if (isset($_POST['do_save_data'])) {
|
||||
$this->indexes->doSaveData(
|
||||
$request,
|
||||
$previewSql = $request->hasBodyParam('preview_sql');
|
||||
if (isset($_POST['old_index'])) {
|
||||
$oldIndex = is_array($_POST['old_index']) ? $_POST['old_index']['Key_name'] : $_POST['old_index'];
|
||||
} else {
|
||||
$oldIndex = null;
|
||||
}
|
||||
|
||||
$sqlQuery = $this->indexes->getSqlQueryForIndexCreateOrEdit(
|
||||
$oldIndex,
|
||||
$index,
|
||||
false,
|
||||
Current::$database,
|
||||
Current::$table,
|
||||
$request->hasBodyParam('preview_sql'),
|
||||
);
|
||||
|
||||
// If there is a request for SQL previewing.
|
||||
if ($previewSql) {
|
||||
$this->response->addJSON(
|
||||
'sql_data',
|
||||
$this->template->render('preview_sql', ['query_data' => $sqlQuery]),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$logicError = $this->indexes->getError();
|
||||
if ($logicError instanceof Message) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', $logicError);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->dbi->query($sqlQuery);
|
||||
|
||||
if ($request->isAjax()) {
|
||||
$message = Message::success(
|
||||
__('Table %1$s has been altered successfully.'),
|
||||
);
|
||||
$message->addParam(Current::$table);
|
||||
$this->response->addJSON(
|
||||
'message',
|
||||
Generator::getMessage($message, $sqlQuery, 'success'),
|
||||
);
|
||||
|
||||
$indexes = Index::getFromTable($this->dbi, Current::$table, Current::$database);
|
||||
$indexesDuplicates = Index::findDuplicates(Current::$table, Current::$database);
|
||||
|
||||
$this->response->addJSON(
|
||||
'index_table',
|
||||
$this->template->render('indexes', [
|
||||
'url_params' => ['db' => Current::$database, 'table' => Current::$table],
|
||||
'indexes' => $indexes,
|
||||
'indexes_duplicates' => $indexesDuplicates,
|
||||
]),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var StructureController $controller */
|
||||
$controller = ContainerBuilder::getContainer()->get(StructureController::class);
|
||||
$controller($request);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -209,7 +209,7 @@ class Index
|
||||
$key .= $params['Seq_in_index'];
|
||||
}
|
||||
|
||||
if (strlen($key) <= 0) {
|
||||
if ($key === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -4,116 +4,176 @@ declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Table;
|
||||
|
||||
use PhpMyAdmin\Container\ContainerBuilder;
|
||||
use PhpMyAdmin\Controllers\Table\StructureController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Html\Generator;
|
||||
use PhpMyAdmin\Http\ServerRequest;
|
||||
use PhpMyAdmin\Identifiers\DatabaseName;
|
||||
use PhpMyAdmin\Index;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Query\Compatibility;
|
||||
use PhpMyAdmin\Query\Generator as QueryGenerator;
|
||||
use PhpMyAdmin\ResponseRenderer;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function sprintf;
|
||||
|
||||
final class Indexes
|
||||
{
|
||||
public function __construct(
|
||||
protected ResponseRenderer $response,
|
||||
protected Template $template,
|
||||
private DatabaseInterface $dbi,
|
||||
) {
|
||||
private Message|null $error = null;
|
||||
|
||||
public function __construct(private readonly DatabaseInterface $dbi)
|
||||
{
|
||||
}
|
||||
|
||||
public function getError(): Message|null
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the data from the edit/create index form,
|
||||
* run the query to build the new index
|
||||
* and moves back to /table/sql
|
||||
* Function to get the sql query for index creation or edit
|
||||
*
|
||||
* @param Index $index An Index instance.
|
||||
* @param bool $renameMode Rename the Index mode
|
||||
* @param Index $index current index
|
||||
*/
|
||||
public function doSaveData(
|
||||
ServerRequest $request,
|
||||
public function getSqlQueryForIndexCreateOrEdit(
|
||||
string|null $oldIndexName,
|
||||
Index $index,
|
||||
bool $renameMode,
|
||||
string $db,
|
||||
string $table,
|
||||
bool $previewSql,
|
||||
string $oldIndexName = '',
|
||||
): void {
|
||||
$error = false;
|
||||
if ($renameMode && Compatibility::isCompatibleRenameIndex($this->dbi->getVersion())) {
|
||||
string $dbName,
|
||||
string $tableName,
|
||||
): string {
|
||||
// $sql_query is the one displayed in the query box
|
||||
$sqlQuery = sprintf(
|
||||
'ALTER TABLE %s.%s',
|
||||
Util::backquote($dbName),
|
||||
Util::backquote($tableName),
|
||||
);
|
||||
|
||||
// Drops the old index
|
||||
if ($oldIndexName !== null) {
|
||||
if ($oldIndexName === 'PRIMARY') {
|
||||
if ($index->getName() === '') {
|
||||
$sqlQuery .= ' DROP PRIMARY KEY,';
|
||||
} else {
|
||||
$sqlQuery .= sprintf(
|
||||
' DROP INDEX %s,',
|
||||
Util::backquote($oldIndexName),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Builds the new one
|
||||
switch ($index->getChoice()) {
|
||||
case 'PRIMARY':
|
||||
if ($index->getName() == '') {
|
||||
$index->setName('PRIMARY');
|
||||
} elseif ($index->getName() !== 'PRIMARY') {
|
||||
$error = Message::error(
|
||||
$this->error = Message::error(
|
||||
__('The name of the primary key must be "PRIMARY"!'),
|
||||
);
|
||||
}
|
||||
|
||||
$sqlQuery .= ' ADD PRIMARY KEY';
|
||||
break;
|
||||
case 'FULLTEXT':
|
||||
case 'UNIQUE':
|
||||
case 'INDEX':
|
||||
case 'SPATIAL':
|
||||
if ($index->getName() === 'PRIMARY') {
|
||||
$this->error = Message::error(
|
||||
__('Can\'t rename index to PRIMARY!'),
|
||||
);
|
||||
}
|
||||
|
||||
$sqlQuery .= sprintf(
|
||||
' ADD %s',
|
||||
$index->getChoice(),
|
||||
);
|
||||
if ($index->getName() !== '') {
|
||||
$sqlQuery .= ' ' . Util::backquote($index->getName());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$indexFields = [];
|
||||
foreach ($index->getColumns() as $key => $column) {
|
||||
$indexFields[$key] = Util::backquote($column->getName());
|
||||
if (! $column->getSubPart()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sqlQuery = QueryGenerator::getSqlQueryForIndexRename(
|
||||
$db,
|
||||
$table,
|
||||
$oldIndexName,
|
||||
$index->getName(),
|
||||
);
|
||||
$indexFields[$key] .= '(' . $column->getSubPart() . ')';
|
||||
}
|
||||
|
||||
if ($indexFields === []) {
|
||||
$this->error = Message::error(__('No index parts defined!'));
|
||||
} else {
|
||||
$sqlQuery = $this->dbi->getTable($db, $table)
|
||||
->getSqlQueryForIndexCreateOrEdit($index, $error);
|
||||
$sqlQuery .= ' (' . implode(', ', $indexFields) . ')';
|
||||
}
|
||||
|
||||
// If there is a request for SQL previewing.
|
||||
if ($previewSql) {
|
||||
$this->response->addJSON(
|
||||
'sql_data',
|
||||
$this->template->render('preview_sql', ['query_data' => $sqlQuery]),
|
||||
);
|
||||
|
||||
return;
|
||||
$keyBlockSizes = $index->getKeyBlockSize();
|
||||
if ($keyBlockSizes !== 0) {
|
||||
$sqlQuery .= ' KEY_BLOCK_SIZE = ' . $keyBlockSizes;
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', $error);
|
||||
|
||||
return;
|
||||
// specifying index type is allowed only for primary, unique and index only
|
||||
// TokuDB is using Fractal Tree, Using Type is not useless
|
||||
// Ref: https://mariadb.com/kb/en/storage-engine-index-types/
|
||||
$type = $index->getType();
|
||||
if (
|
||||
$index->getChoice() !== 'SPATIAL'
|
||||
&& $index->getChoice() !== 'FULLTEXT'
|
||||
&& in_array($type, Index::getIndexTypes(), true)
|
||||
&& ! $this->dbi->getTable($dbName, $tableName)->isEngine('TOKUDB')
|
||||
) {
|
||||
$sqlQuery .= ' USING ' . $type;
|
||||
}
|
||||
|
||||
$this->dbi->query($sqlQuery);
|
||||
if ($request->isAjax()) {
|
||||
$message = Message::success(
|
||||
__('Table %1$s has been altered successfully.'),
|
||||
);
|
||||
$message->addParam($table);
|
||||
$this->response->addJSON(
|
||||
'message',
|
||||
Generator::getMessage($message, $sqlQuery, 'success'),
|
||||
);
|
||||
|
||||
$indexes = Index::getFromTable($this->dbi, $table, $db);
|
||||
$indexesDuplicates = Index::findDuplicates($table, $db);
|
||||
|
||||
$this->response->addJSON(
|
||||
'index_table',
|
||||
$this->template->render('indexes', [
|
||||
'url_params' => ['db' => $db, 'table' => $table],
|
||||
'indexes' => $indexes,
|
||||
'indexes_duplicates' => $indexesDuplicates,
|
||||
]),
|
||||
);
|
||||
|
||||
return;
|
||||
$parser = $index->getParser();
|
||||
if ($index->getChoice() === 'FULLTEXT' && $parser !== '') {
|
||||
$sqlQuery .= ' WITH PARSER ' . $parser;
|
||||
}
|
||||
|
||||
/** @var StructureController $controller */
|
||||
$controller = ContainerBuilder::getContainer()->get(StructureController::class);
|
||||
$controller($request);
|
||||
$comment = $index->getComment();
|
||||
if ($comment !== '') {
|
||||
$sqlQuery .= sprintf(
|
||||
' COMMENT %s',
|
||||
$this->dbi->quoteString($comment),
|
||||
);
|
||||
}
|
||||
|
||||
$sqlQuery .= ';';
|
||||
|
||||
return $sqlQuery;
|
||||
}
|
||||
|
||||
public function getSqlQueryForRename(string $oldIndexName, Index $index, string $db, string $table): string
|
||||
{
|
||||
if (! Compatibility::isCompatibleRenameIndex($this->dbi->getVersion())) {
|
||||
return $this->getSqlQueryForIndexCreateOrEdit($oldIndexName, $index, $db, $table);
|
||||
}
|
||||
|
||||
if ($oldIndexName === 'PRIMARY') {
|
||||
if ($index->getName() === '') {
|
||||
$index->setName('PRIMARY');
|
||||
} elseif ($index->getName() !== 'PRIMARY') {
|
||||
$this->error = Message::error(
|
||||
__('The name of the primary key must be "PRIMARY"!'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($index->getName() === 'PRIMARY') {
|
||||
$this->error = Message::error(
|
||||
__('Can\'t rename index to PRIMARY!'),
|
||||
);
|
||||
}
|
||||
|
||||
return QueryGenerator::getSqlQueryForIndexRename(
|
||||
$db,
|
||||
$table,
|
||||
$oldIndexName,
|
||||
$index->getName(),
|
||||
);
|
||||
}
|
||||
|
||||
public function executeAddIndexSql(string|DatabaseName $db, string $sql): Message
|
||||
|
||||
@ -1875,120 +1875,6 @@ class Table implements Stringable
|
||||
return Index::singleton($this->dbi, $this->dbName, $this->name, $index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the sql query for index creation or edit
|
||||
*
|
||||
* @param Index $index current index
|
||||
* @param bool $error whether error occurred or not
|
||||
*/
|
||||
public function getSqlQueryForIndexCreateOrEdit(Index $index, bool &$error): string
|
||||
{
|
||||
// $sql_query is the one displayed in the query box
|
||||
$sqlQuery = sprintf(
|
||||
'ALTER TABLE %s.%s',
|
||||
Util::backquote($this->dbName),
|
||||
Util::backquote($this->name),
|
||||
);
|
||||
|
||||
// Drops the old index
|
||||
if (! empty($_POST['old_index'])) {
|
||||
$oldIndex = is_array($_POST['old_index']) ? $_POST['old_index']['Key_name'] : $_POST['old_index'];
|
||||
if ($oldIndex === 'PRIMARY') {
|
||||
$sqlQuery .= ' DROP PRIMARY KEY,';
|
||||
} else {
|
||||
$sqlQuery .= sprintf(
|
||||
' DROP INDEX %s,',
|
||||
Util::backquote($oldIndex),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Builds the new one
|
||||
switch ($index->getChoice()) {
|
||||
case 'PRIMARY':
|
||||
if ($index->getName() == '') {
|
||||
$index->setName('PRIMARY');
|
||||
} elseif ($index->getName() !== 'PRIMARY') {
|
||||
$error = Message::error(
|
||||
__('The name of the primary key must be "PRIMARY"!'),
|
||||
);
|
||||
}
|
||||
|
||||
$sqlQuery .= ' ADD PRIMARY KEY';
|
||||
break;
|
||||
case 'FULLTEXT':
|
||||
case 'UNIQUE':
|
||||
case 'INDEX':
|
||||
case 'SPATIAL':
|
||||
if ($index->getName() === 'PRIMARY') {
|
||||
$error = Message::error(
|
||||
__('Can\'t rename index to PRIMARY!'),
|
||||
);
|
||||
}
|
||||
|
||||
$sqlQuery .= sprintf(
|
||||
' ADD %s',
|
||||
$index->getChoice(),
|
||||
);
|
||||
if ($index->getName() !== '') {
|
||||
$sqlQuery .= ' ' . Util::backquote($index->getName());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$indexFields = [];
|
||||
foreach ($index->getColumns() as $key => $column) {
|
||||
$indexFields[$key] = Util::backquote($column->getName());
|
||||
if (! $column->getSubPart()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$indexFields[$key] .= '(' . $column->getSubPart() . ')';
|
||||
}
|
||||
|
||||
if ($indexFields === []) {
|
||||
$error = Message::error(__('No index parts defined!'));
|
||||
} else {
|
||||
$sqlQuery .= ' (' . implode(', ', $indexFields) . ')';
|
||||
}
|
||||
|
||||
$keyBlockSizes = $index->getKeyBlockSize();
|
||||
if ($keyBlockSizes !== 0) {
|
||||
$sqlQuery .= ' KEY_BLOCK_SIZE = ' . $keyBlockSizes;
|
||||
}
|
||||
|
||||
// specifying index type is allowed only for primary, unique and index only
|
||||
// TokuDB is using Fractal Tree, Using Type is not useless
|
||||
// Ref: https://mariadb.com/kb/en/storage-engine-index-types/
|
||||
$type = $index->getType();
|
||||
if (
|
||||
$index->getChoice() !== 'SPATIAL'
|
||||
&& $index->getChoice() !== 'FULLTEXT'
|
||||
&& in_array($type, Index::getIndexTypes(), true)
|
||||
&& ! $this->isEngine('TOKUDB')
|
||||
) {
|
||||
$sqlQuery .= ' USING ' . $type;
|
||||
}
|
||||
|
||||
$parser = $index->getParser();
|
||||
if ($index->getChoice() === 'FULLTEXT' && $parser !== '') {
|
||||
$sqlQuery .= ' WITH PARSER ' . $parser;
|
||||
}
|
||||
|
||||
$comment = $index->getComment();
|
||||
if ($comment !== '') {
|
||||
$sqlQuery .= sprintf(
|
||||
' COMMENT %s',
|
||||
$this->dbi->quoteString($comment),
|
||||
);
|
||||
}
|
||||
|
||||
$sqlQuery .= ';';
|
||||
|
||||
return $sqlQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to handle update for display field
|
||||
*
|
||||
|
||||
@ -24,31 +24,32 @@ class IndexRenameControllerTest extends AbstractTestCase
|
||||
public function testIndexRenameController(): void
|
||||
{
|
||||
Current::$database = 'test_db';
|
||||
Current::$table = 'test_table';
|
||||
Current::$table = 'test_table_index_rename';
|
||||
$GLOBALS['lang'] = 'en';
|
||||
|
||||
$dummyDbi = $this->createDbiDummy();
|
||||
$dummyDbi->addSelectDb('test_db');
|
||||
$dummyDbi->addSelectDb('test_db');
|
||||
$dummyDbi->addResult('SELECT 1 FROM `test_db`.`test_table` LIMIT 1;', [['1']]);
|
||||
$dummyDbi->addResult('SELECT 1 FROM `test_db`.`test_table_index_rename` LIMIT 1;', [['1']]);
|
||||
$dbi = $this->createDatabaseInterface($dummyDbi);
|
||||
DatabaseInterface::$instance = $dbi;
|
||||
|
||||
$template = new Template();
|
||||
$expected = $template->render('table/index_rename_form', [
|
||||
'index' => new Index(),
|
||||
'form_params' => ['db' => 'test_db', 'table' => 'test_table'],
|
||||
'index' => new Index(['Key_name' => 'index']),
|
||||
'form_params' => ['db' => 'test_db', 'table' => 'test_table_index_rename', 'old_index' => 'index'],
|
||||
]);
|
||||
|
||||
$request = ServerRequestFactory::create()->createServerRequest('GET', 'http://example.com/')
|
||||
->withQueryParams(['db' => 'test_db', 'table' => 'test_table']);
|
||||
->withQueryParams(['db' => 'test_db', 'table' => 'test_table_index_rename'])
|
||||
->withParsedBody(['index' => 'index']);
|
||||
|
||||
$response = new ResponseRenderer();
|
||||
(new IndexRenameController(
|
||||
$response,
|
||||
$template,
|
||||
$dbi,
|
||||
new Indexes($response, $template, $dbi),
|
||||
new Indexes($dbi),
|
||||
new DbTableExists($dbi),
|
||||
))($request);
|
||||
$this->assertSame($expected, $response->getHTMLResult());
|
||||
@ -62,9 +63,9 @@ class IndexRenameControllerTest extends AbstractTestCase
|
||||
Config::getInstance()->selectedServer['DisableIS'] = true;
|
||||
|
||||
Current::$database = 'test_db';
|
||||
Current::$table = 'test_table';
|
||||
Current::$table = 'test_table_index_rename';
|
||||
$_POST['db'] = 'test_db';
|
||||
$_POST['table'] = 'test_table';
|
||||
$_POST['table'] = 'test_table_index_rename';
|
||||
$_POST['old_index'] = 'old_name';
|
||||
$_POST['index'] = ['Key_name' => 'new_name'];
|
||||
$_POST['do_save_data'] = '1';
|
||||
@ -72,12 +73,12 @@ class IndexRenameControllerTest extends AbstractTestCase
|
||||
|
||||
$dbiDummy = $this->createDbiDummy();
|
||||
$dbiDummy->addSelectDb('test_db');
|
||||
$dbiDummy->addResult('SELECT 1 FROM `test_db`.`test_table` LIMIT 1;', [['1']], ['1']);
|
||||
$dbiDummy->addResult('SELECT 1 FROM `test_db`.`test_table_index_rename` LIMIT 1;', [['1']], ['1']);
|
||||
$dbiDummy->addResult(
|
||||
'SHOW INDEXES FROM `test_db`.`test_table`',
|
||||
'SHOW INDEXES FROM `test_db`.`test_table_index_rename`',
|
||||
[
|
||||
['test_table', '0', 'PRIMARY', 'id', 'BTREE'],
|
||||
['test_table', '1', 'old_name', 'name', 'BTREE'],
|
||||
['test_table_index_rename', '0', 'PRIMARY', 'id', 'BTREE'],
|
||||
['test_table_index_rename', '1', 'old_name', 'name', 'BTREE'],
|
||||
],
|
||||
['Table', 'Non_unique', 'Key_name', 'Column_name', 'Index_type'],
|
||||
);
|
||||
@ -89,17 +90,17 @@ class IndexRenameControllerTest extends AbstractTestCase
|
||||
$expected = <<<'HTML'
|
||||
<div class="preview_sql">
|
||||
<code class="sql" dir="ltr"><pre>
|
||||
ALTER TABLE `test_db`.`test_table` DROP INDEX `old_name`, ADD INDEX `new_name` (`name`) USING BTREE;
|
||||
ALTER TABLE `test_db`.`test_table_index_rename` DROP INDEX `old_name`, ADD INDEX `new_name` (`name`) USING BTREE;
|
||||
</pre></code>
|
||||
</div>
|
||||
|
||||
HTML;
|
||||
|
||||
$request = ServerRequestFactory::create()->createServerRequest('GET', 'http://example.com/')
|
||||
->withQueryParams(['db' => 'test_db', 'table' => 'test_table'])
|
||||
->withQueryParams(['db' => 'test_db', 'table' => 'test_table_index_rename'])
|
||||
->withParsedBody([
|
||||
'old_index' => 'old_name',
|
||||
'index' => ['Key_name' => 'new_name'],
|
||||
'index' => 'new_name',
|
||||
'do_save_data' => '1',
|
||||
'preview_sql' => '1',
|
||||
]);
|
||||
@ -110,7 +111,7 @@ HTML;
|
||||
$responseRenderer,
|
||||
$template,
|
||||
$dbi,
|
||||
new Indexes($responseRenderer, $template, $dbi),
|
||||
new Indexes($dbi),
|
||||
new DbTableExists($dbi),
|
||||
);
|
||||
$controller($request);
|
||||
|
||||
@ -96,7 +96,7 @@ class IndexesControllerTest extends AbstractTestCase
|
||||
$response,
|
||||
$template,
|
||||
$dbi,
|
||||
new Indexes($response, $template, $dbi),
|
||||
new Indexes($dbi),
|
||||
new DbTableExists($dbi),
|
||||
);
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ class SpatialControllerTest extends AbstractTestCase
|
||||
$controllerStub = $this->createMock(StructureController::class);
|
||||
$controllerStub->expects($this->once())->method('__invoke')->with($request);
|
||||
|
||||
$indexes = new Indexes(new ResponseRenderer(), new Template(), DatabaseInterface::getInstance());
|
||||
$indexes = new Indexes(DatabaseInterface::getInstance());
|
||||
$controller = new SpatialController(new ResponseRenderer(), new Template(), $controllerStub, $indexes);
|
||||
$controller($request);
|
||||
|
||||
@ -64,7 +64,7 @@ class SpatialControllerTest extends AbstractTestCase
|
||||
$controllerStub = $this->createMock(StructureController::class);
|
||||
$controllerStub->expects($this->once())->method('__invoke')->with($request);
|
||||
|
||||
$indexes = new Indexes(new ResponseRenderer(), new Template(), DatabaseInterface::getInstance());
|
||||
$indexes = new Indexes(DatabaseInterface::getInstance());
|
||||
$controller = new SpatialController(new ResponseRenderer(), new Template(), $controllerStub, $indexes);
|
||||
$controller($request);
|
||||
|
||||
@ -90,7 +90,7 @@ class SpatialControllerTest extends AbstractTestCase
|
||||
$controllerStub->expects($this->never())->method('__invoke');
|
||||
$response = new ResponseRenderer();
|
||||
|
||||
$indexes = new Indexes(new ResponseRenderer(), new Template(), DatabaseInterface::getInstance());
|
||||
$indexes = new Indexes(DatabaseInterface::getInstance());
|
||||
$controller = new SpatialController($response, new Template(), $controllerStub, $indexes);
|
||||
$controller($request);
|
||||
|
||||
@ -120,7 +120,7 @@ class SpatialControllerTest extends AbstractTestCase
|
||||
$controllerStub = $this->createMock(StructureController::class);
|
||||
$controllerStub->expects($this->once())->method('__invoke')->with($request);
|
||||
|
||||
$indexes = new Indexes(new ResponseRenderer(), new Template(), DatabaseInterface::getInstance());
|
||||
$indexes = new Indexes(DatabaseInterface::getInstance());
|
||||
$controller = new SpatialController(new ResponseRenderer(), new Template(), $controllerStub, $indexes);
|
||||
$controller($request);
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ class UniqueControllerTest extends AbstractTestCase
|
||||
$controllerStub = $this->createMock(StructureController::class);
|
||||
$controllerStub->expects($this->once())->method('__invoke')->with($request);
|
||||
|
||||
$indexes = new Indexes(new ResponseRenderer(), new Template(), DatabaseInterface::getInstance());
|
||||
$indexes = new Indexes(DatabaseInterface::getInstance());
|
||||
$controller = new UniqueController(new ResponseRenderer(), new Template(), $controllerStub, $indexes);
|
||||
$controller($request);
|
||||
|
||||
@ -64,7 +64,7 @@ class UniqueControllerTest extends AbstractTestCase
|
||||
$controllerStub = $this->createMock(StructureController::class);
|
||||
$controllerStub->expects($this->once())->method('__invoke')->with($request);
|
||||
|
||||
$indexes = new Indexes(new ResponseRenderer(), new Template(), DatabaseInterface::getInstance());
|
||||
$indexes = new Indexes(DatabaseInterface::getInstance());
|
||||
$controller = new UniqueController(new ResponseRenderer(), new Template(), $controllerStub, $indexes);
|
||||
$controller($request);
|
||||
|
||||
@ -90,7 +90,7 @@ class UniqueControllerTest extends AbstractTestCase
|
||||
$controllerStub->expects($this->never())->method('__invoke');
|
||||
$response = new ResponseRenderer();
|
||||
|
||||
$indexes = new Indexes(new ResponseRenderer(), new Template(), DatabaseInterface::getInstance());
|
||||
$indexes = new Indexes(DatabaseInterface::getInstance());
|
||||
$controller = new UniqueController($response, new Template(), $controllerStub, $indexes);
|
||||
$controller($request);
|
||||
|
||||
@ -120,7 +120,7 @@ class UniqueControllerTest extends AbstractTestCase
|
||||
$controllerStub = $this->createMock(StructureController::class);
|
||||
$controllerStub->expects($this->once())->method('__invoke')->with($request);
|
||||
|
||||
$indexes = new Indexes(new ResponseRenderer(), new Template(), DatabaseInterface::getInstance());
|
||||
$indexes = new Indexes(DatabaseInterface::getInstance());
|
||||
$controller = new UniqueController(new ResponseRenderer(), new Template(), $controllerStub, $indexes);
|
||||
$controller($request);
|
||||
|
||||
|
||||
@ -1651,6 +1651,11 @@ class DbiDummy implements DbiExtension
|
||||
'columns' => ['Name', 'Engine', 'Rows'],
|
||||
'result' => [['test_table', 'InnoDB', '3']],
|
||||
],
|
||||
[
|
||||
'query' => 'SHOW TABLE STATUS FROM `test_db` WHERE `Name` LIKE \'test\\\\_table\\\\_index\\\\_rename%\'',
|
||||
'columns' => ['Name', 'Engine', 'Rows'],
|
||||
'result' => [['test_table_index_rename', 'InnoDB', '3']],
|
||||
],
|
||||
[
|
||||
'query' => 'SHOW TABLE STATUS FROM `test_db` WHERE Name = \'test_table\'',
|
||||
'columns' => ['Name', 'Engine', 'Rows'],
|
||||
@ -1661,6 +1666,11 @@ class DbiDummy implements DbiExtension
|
||||
'columns' => ['Table', 'Non_unique', 'Key_name', 'Column_name'],
|
||||
'result' => [['test_table', '0', 'PRIMARY', 'id']],
|
||||
],
|
||||
[
|
||||
'query' => 'SHOW INDEXES FROM `test_db`.`test_table_index_rename`',
|
||||
'columns' => ['Table', 'Non_unique', 'Key_name', 'Column_name'],
|
||||
'result' => [['test_table_index_rename', '0', 'PRIMARY', 'id']],
|
||||
],
|
||||
[
|
||||
'query' => 'SHOW INDEX FROM `test_table`;',
|
||||
'columns' => ['Table', 'Non_unique', 'Key_name', 'Column_name'],
|
||||
|
||||
@ -4,86 +4,86 @@ declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Tests\Table;
|
||||
|
||||
use PhpMyAdmin\Config;
|
||||
use PhpMyAdmin\Current;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Http\Factory\ServerRequestFactory;
|
||||
use PhpMyAdmin\Index;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Table\Indexes;
|
||||
use PhpMyAdmin\Table\Table;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Tests\AbstractTestCase;
|
||||
use PhpMyAdmin\Tests\Stubs\ResponseRenderer as ResponseStub;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
#[CoversClass(Indexes::class)]
|
||||
class IndexesTest extends AbstractTestCase
|
||||
{
|
||||
private DatabaseInterface&MockObject $dbi;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
/**
|
||||
* SET these to avoid undefined index error
|
||||
*/
|
||||
Current::$database = 'db';
|
||||
Current::$table = 'table';
|
||||
$config = Config::getInstance();
|
||||
$config->selectedServer['pmadb'] = '';
|
||||
$config->selectedServer['DisableIS'] = false;
|
||||
$GLOBALS['urlParams'] = ['db' => 'db', 'server' => 1];
|
||||
|
||||
$dbi = $this->getMockBuilder(DatabaseInterface::class)
|
||||
$this->dbi = $this->getMockBuilder(DatabaseInterface::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$indexs = [
|
||||
['Schema' => 'Schema1', 'Key_name' => 'Key_name1', 'Column_name' => 'Column_name1'],
|
||||
['Schema' => 'Schema2', 'Key_name' => 'Key_name2', 'Column_name' => 'Column_name2'],
|
||||
['Schema' => 'Schema3', 'Key_name' => 'Key_name3', 'Column_name' => 'Column_name3'],
|
||||
];
|
||||
|
||||
$dbi->expects($this->any())->method('getTableIndexes')
|
||||
->willReturn($indexs);
|
||||
|
||||
DatabaseInterface::$instance = $dbi;
|
||||
|
||||
//$_SESSION
|
||||
}
|
||||
|
||||
public function testDoSaveData(): void
|
||||
public function testGetSqlQueryForRename(): void
|
||||
{
|
||||
$sqlQuery = 'ALTER TABLE `db`.`table` DROP PRIMARY KEY, ADD UNIQUE ;';
|
||||
$sqlQuery = 'ALTER TABLE `db`.`table` RENAME INDEX `0` TO `ABC`;';
|
||||
|
||||
$this->dbi->expects($this->any())->method('getVersion')
|
||||
->willReturn(50700);
|
||||
|
||||
$index = new Index(['Key_name' => 'ABC']);
|
||||
|
||||
$indexes = new Indexes($this->dbi);
|
||||
|
||||
$sqlResult = $indexes->getSqlQueryForRename('0', $index, Current::$database, Current::$table);
|
||||
$this->assertStringContainsString($sqlQuery, $sqlResult);
|
||||
|
||||
// Error message
|
||||
$index->setName('NOT PRIMARY'); // Cannot rename primary so the operation should fail
|
||||
$indexes->getSqlQueryForRename('PRIMARY', $index, Current::$database, Current::$table);
|
||||
$error = $indexes->getError();
|
||||
$this->assertInstanceOf(Message::class, $error);
|
||||
|
||||
$index->setName('PRIMARY'); // The new name cannot be PRIMARY so the operation should fail
|
||||
$indexes->getSqlQueryForRename('NOT PRIMARY', $index, Current::$database, Current::$table);
|
||||
$error = $indexes->getError();
|
||||
$this->assertInstanceOf(Message::class, $error);
|
||||
}
|
||||
|
||||
public function testGetSqlQueryForIndexCreateOrEdit(): void
|
||||
{
|
||||
$table = $this->getMockBuilder(Table::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$table->expects($this->any())->method('getSqlQueryForIndexCreateOrEdit')
|
||||
->willReturn($sqlQuery);
|
||||
|
||||
$dbi = DatabaseInterface::getInstance();
|
||||
$dbi->expects($this->any())->method('getTable')
|
||||
$this->dbi->expects($this->any())->method('getTable')
|
||||
->willReturn($table);
|
||||
$indexes = new Indexes($this->dbi);
|
||||
|
||||
$response = new ResponseStub();
|
||||
$index = new Index();
|
||||
$db = 'pma_db';
|
||||
$table = 'pma_table';
|
||||
$index = new Index([
|
||||
'Key_name' => 'PRIMARY',
|
||||
'columns' => [['Column_name' => 'id']],
|
||||
]);
|
||||
|
||||
$indexes = new Indexes($response, new Template(), $dbi);
|
||||
$sqlQueryExpected = 'ALTER TABLE `pma_db`.`pma_table` DROP PRIMARY KEY, ADD PRIMARY KEY (`id`);';
|
||||
|
||||
$request = ServerRequestFactory::create()->createServerRequest('GET', 'http://example.com/')
|
||||
->withQueryParams(['ajax_request' => '1']);
|
||||
$_POST['old_index'] = 'PRIMARY';
|
||||
$this->assertEquals(
|
||||
$sqlQueryExpected,
|
||||
$indexes->getSqlQueryForIndexCreateOrEdit('PRIMARY', $index, $db, $table),
|
||||
);
|
||||
|
||||
// Preview SQL
|
||||
$indexes->doSaveData($request, $index, false, Current::$database, Current::$table, true);
|
||||
$jsonArray = $response->getJSONResult();
|
||||
$this->assertArrayHasKey('sql_data', $jsonArray);
|
||||
$this->assertStringContainsString($sqlQuery, $jsonArray['sql_data']);
|
||||
|
||||
// Alter success
|
||||
$response->clear();
|
||||
$indexes->doSaveData($request, $index, false, Current::$database, Current::$table, false);
|
||||
$jsonArray = $response->getJSONResult();
|
||||
$this->assertArrayHasKey('index_table', $jsonArray);
|
||||
$this->assertArrayHasKey('message', $jsonArray);
|
||||
// Error message
|
||||
$index->setName('NOT PRIMARY'); // Cannot rename primary so the operation should fail
|
||||
$indexes->getSqlQueryForIndexCreateOrEdit('PRIMARY', $index, $db, $table);
|
||||
$this->assertInstanceOf(Message::class, $indexes->getError());
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ use PhpMyAdmin\ConfigStorage\Relation;
|
||||
use PhpMyAdmin\ConfigStorage\RelationParameters;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Dbal\Connection;
|
||||
use PhpMyAdmin\Index;
|
||||
use PhpMyAdmin\ListDatabase;
|
||||
use PhpMyAdmin\Query\Cache;
|
||||
use PhpMyAdmin\SqlParser\Context;
|
||||
@ -1180,42 +1179,6 @@ class TableTest extends AbstractTestCase
|
||||
$this->assertEquals($sqlExcepted, $sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for getSqlQueryForIndexCreateOrEdit() method.
|
||||
*/
|
||||
public function testGetSqlQueryForIndexCreateOrEdit(): void
|
||||
{
|
||||
$db = 'pma_db';
|
||||
$table = 'pma_table';
|
||||
$index = new Index();
|
||||
$error = false;
|
||||
|
||||
$_POST['old_index'] = 'PRIMARY';
|
||||
|
||||
$table = new Table($table, $db, DatabaseInterface::getInstance());
|
||||
$sql = $table->getSqlQueryForIndexCreateOrEdit($index, $error);
|
||||
|
||||
$this->assertEquals('ALTER TABLE `pma_db`.`pma_table` DROP PRIMARY KEY, ADD UNIQUE;', $sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for getSqlQueryForIndexCreateOrEdit() method.
|
||||
*/
|
||||
public function testGetSqlQueryForIndexCreateOrEditSecondFormat(): void
|
||||
{
|
||||
$db = 'pma_db';
|
||||
$table = 'pma_table';
|
||||
$index = new Index();
|
||||
$error = false;
|
||||
|
||||
$_POST['old_index']['Key_name'] = 'PRIMARY';
|
||||
|
||||
$table = new Table($table, $db, DatabaseInterface::getInstance());
|
||||
$sql = $table->getSqlQueryForIndexCreateOrEdit($index, $error);
|
||||
|
||||
$this->assertEquals('ALTER TABLE `pma_db`.`pma_table` DROP PRIMARY KEY, ADD UNIQUE;', $sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for getColumns
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user