Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Alter rename --------- Co-authored-by: djklim87 <klim@manticoresearch.com>
- Loading branch information
Showing
3 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
<?php declare(strict_types=1); | ||
|
||
/* | ||
Copyright (c) 2024, Manticore Software LTD (https://manticoresearch.com) | ||
This program is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License version 2 or any later | ||
version. You should have received a copy of the GPL license along with this | ||
program; if you did not, you can find it at http://www.gnu.org/ | ||
*/ | ||
|
||
namespace Manticoresearch\Buddy\Base\Plugin\AlterRenameTable; | ||
|
||
use Manticoresearch\Buddy\Core\Error\GenericError; | ||
use Manticoresearch\Buddy\Core\Error\ManticoreSearchClientError; | ||
use Manticoresearch\Buddy\Core\ManticoreSearch\Client; | ||
use Manticoresearch\Buddy\Core\Plugin\BaseHandlerWithClient; | ||
use Manticoresearch\Buddy\Core\Task\Task; | ||
use Manticoresearch\Buddy\Core\Task\TaskResult; | ||
use RuntimeException; | ||
|
||
final class Handler extends BaseHandlerWithClient | ||
{ | ||
|
||
/** | ||
* Initialize the executor | ||
* | ||
* @param Payload $payload | ||
* @return void | ||
*/ | ||
public function __construct(public Payload $payload) { | ||
} | ||
|
||
/** | ||
* Process the request | ||
* | ||
* @return Task | ||
* @throws RuntimeException | ||
*/ | ||
public function run(): Task { | ||
$taskFn = static function (Payload $payload, Client $client): TaskResult { | ||
|
||
if (!$client->hasTable($payload->sourceTableName)) { | ||
throw GenericError::create("Source table $payload->sourceTableName not exists"); | ||
} | ||
|
||
if ($client->hasTable($payload->destinationTableName)) { | ||
throw GenericError::create("Destination table $payload->destinationTableName already exists"); | ||
} | ||
self::createTableLike($payload->sourceTableName, $payload->destinationTableName, $client); | ||
|
||
$result = (array)self::attachTable($payload->sourceTableName, $payload->destinationTableName, $client); | ||
|
||
self::dropTable($payload->sourceTableName, $client); | ||
|
||
return TaskResult::raw($result); | ||
}; | ||
|
||
return Task::create( | ||
$taskFn, [$this->payload, $this->manticoreClient] | ||
)->run(); | ||
} | ||
|
||
|
||
/** | ||
* @param string $sourceTableName | ||
* @param string $destinationTableName | ||
* @param Client $client | ||
* @return void | ||
* @throws GenericError | ||
* @throws ManticoreSearchClientError | ||
*/ | ||
private static function createTableLike( | ||
string $sourceTableName, | ||
string $destinationTableName, | ||
Client $client | ||
): void { | ||
|
||
$sql = /** @lang ManticoreSearch */ | ||
"create table $destinationTableName like $sourceTableName"; | ||
$result = $client->sendRequest($sql); | ||
if ($result->hasError()) { | ||
throw GenericError::create( | ||
"Can't create $destinationTableName table like $sourceTableName. " . | ||
'Reason: ' . $result->getError() | ||
); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* @param string $sourceTableName | ||
* @param string $destinationTableName | ||
* @param Client $client | ||
* @return mixed | ||
* @throws GenericError | ||
* @throws ManticoreSearchClientError | ||
*/ | ||
private static function attachTable( | ||
string $sourceTableName, | ||
string $destinationTableName, | ||
Client $client | ||
): mixed { | ||
|
||
$sql = /** @lang ManticoreSearch */ | ||
"ATTACH TABLE $sourceTableName TO TABLE $destinationTableName"; | ||
$result = $client->sendRequest($sql); | ||
if ($result->hasError()) { | ||
throw GenericError::create( | ||
"Can't attach $sourceTableName table to $destinationTableName. " . | ||
'Reason: ' . $result->getError() | ||
); | ||
} | ||
return $result->getResult(); | ||
} | ||
|
||
|
||
/** | ||
* @param string $tableName | ||
* @param Client $client | ||
* @throws GenericError | ||
* @throws ManticoreSearchClientError | ||
*/ | ||
private static function dropTable(string $tableName, Client $client): void { | ||
$sql = /** @lang ManticoreSearch */ | ||
"drop table $tableName"; | ||
$result = $client->sendRequest($sql); | ||
if ($result->hasError()) { | ||
throw GenericError::create("Can't drop table $tableName. Reason: " . $result->getError()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
<?php declare(strict_types=1); | ||
|
||
/* | ||
Copyright (c) 2024, Manticore Software LTD (https://manticoresearch.com) | ||
This program is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License version 2 or any later | ||
version. You should have received a copy of the GPL license along with this | ||
program; if you did not, you can find it at http://www.gnu.org/ | ||
*/ | ||
|
||
namespace Manticoresearch\Buddy\Base\Plugin\AlterRenameTable; | ||
|
||
use Manticoresearch\Buddy\Core\Error\GenericError; | ||
use Manticoresearch\Buddy\Core\Network\Request; | ||
use Manticoresearch\Buddy\Core\Plugin\BasePayload; | ||
|
||
/** | ||
* This is simple do nothing request that handle empty queries | ||
* which can be as a result of only comments in it that we strip | ||
* @extends BasePayload<array> | ||
*/ | ||
final class Payload extends BasePayload { | ||
public string $path; | ||
|
||
public string $destinationTableName; | ||
public string $sourceTableName; | ||
|
||
public string $type; | ||
|
||
/** | ||
* Get description for this plugin | ||
* @return string | ||
*/ | ||
public static function getInfo(): string { | ||
return 'Enables alter table rename'; | ||
} | ||
|
||
/** | ||
* @param Request $request | ||
* @return static | ||
*/ | ||
public static function fromRequest(Request $request): static { | ||
$self = new static(); | ||
/** phpstan fix */ | ||
unset($request); | ||
/** | ||
* @phpstan-var array{ | ||
* ALTER: array{ | ||
* expr_type: string, | ||
* base_expr: string, | ||
* sub_tree: array< | ||
* array{ | ||
* expr_type: string, | ||
* base_expr: string | ||
* }> | ||
* }, | ||
* TABLE: array{ | ||
* base_expr: string, | ||
* name: string, | ||
* no_quotes: array{ | ||
* delim: bool, | ||
* parts: array<string> | ||
* }, | ||
* create-def: bool, | ||
* options: bool | ||
* }, | ||
* RENAME: array{ | ||
* expr_type: string, | ||
* sub_tree: array< | ||
* array{ | ||
* destination: array{ | ||
* expr_type: string, | ||
* table: string, | ||
* no_quotes: array{ | ||
* delim: bool, | ||
* parts: array<string> | ||
* }, | ||
* base_expr: string | ||
* } | ||
* }> | ||
* } | ||
* } $payload | ||
*/ | ||
$payload = Payload::$sqlQueryParser::getParsedPayload(); | ||
|
||
$self->destinationTableName = $payload['RENAME']['sub_tree'][0]['destination']['no_quotes']['parts'][0]; | ||
$self->sourceTableName = $payload['TABLE']['no_quotes']['parts'][0]; | ||
return $self; | ||
} | ||
|
||
/** | ||
* @param Request $request | ||
* @return bool | ||
* @throws GenericError | ||
*/ | ||
public static function hasMatch(Request $request): bool { | ||
|
||
/** | ||
* @phpstan-var array{ | ||
* ALTER: array{ | ||
* expr_type: string, | ||
* base_expr?: string, | ||
* sub_tree: array< | ||
* array{ | ||
* expr_type: string, | ||
* base_expr: string | ||
* }> | ||
* }, | ||
* TABLE?: array{ | ||
* base_expr: string, | ||
* name: string, | ||
* no_quotes: array{ | ||
* delim: bool, | ||
* parts: array<string> | ||
* }, | ||
* create-def: bool, | ||
* options: bool | ||
* }, | ||
* RENAME?: array{ | ||
* expr_type: string, | ||
* sub_tree: array< | ||
* array{ | ||
* destination: array{ | ||
* expr_type: string, | ||
* table: string, | ||
* no_quotes: array{ | ||
* delim: bool, | ||
* parts: array<string> | ||
* }, | ||
* base_expr: string | ||
* } | ||
* }> | ||
* } | ||
* }|false $payload | ||
*/ | ||
|
||
$payload = Payload::$sqlQueryParser::parse( | ||
$request->payload, | ||
fn(Request $request) => ( | ||
strpos($request->error, 'P03: syntax error, unexpected tablename') === 0 | ||
&& stripos($request->payload, 'alter') !== false | ||
&& stripos($request->payload, 'table') !== false | ||
&& stripos($request->payload, 'rename') !== false | ||
), | ||
$request | ||
); | ||
|
||
if (!$payload) { | ||
return false; | ||
} | ||
|
||
if (isset($payload['ALTER']['base_expr']) | ||
&& isset($payload['TABLE']['no_quotes']['parts'][0]) | ||
&& isset($payload['RENAME']['sub_tree'][0]['destination']['no_quotes']['parts'][0]) | ||
&& $payload['ALTER']['base_expr'] === 'TABLE' | ||
) { | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters