![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/cartforge.co/vendor/magento/module-catalog-rule/Model/Indexer/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ declare(strict_types=1); namespace Magento\CatalogRule\Model\Indexer; use Magento\Framework\App\ResourceConnection; /** * @inheritDoc */ class IndexerTableSwapper implements IndexerTableSwapperInterface { /** * Keys are original tables' names, values - created temporary tables. * * @var string[] */ private $temporaryTables = []; /** * @var ResourceConnection */ private $resourceConnection; /** * @param ResourceConnection $resource */ public function __construct(ResourceConnection $resource) { $this->resourceConnection = $resource; } /** * Create temporary table based on given table to use instead of original. * * @param string $originalTableName * * @return string Created table name. */ private function createTemporaryTable(string $originalTableName): string { $temporaryTableName = $this->resourceConnection->getTableName( $originalTableName . '__temp' . $this->generateRandomSuffix() ); $this->resourceConnection->getConnection()->query( sprintf( 'create table %s like %s', $temporaryTableName, $this->resourceConnection->getTableName($originalTableName) ) ); return $temporaryTableName; } /** * Random suffix for temporary tables not to conflict with each other. * * @return string */ private function generateRandomSuffix(): string { return bin2hex(random_bytes(4)); } /** * @inheritDoc */ public function getWorkingTableName(string $originalTable): string { $originalTable = $this->resourceConnection->getTableName($originalTable); if (!array_key_exists($originalTable, $this->temporaryTables)) { $this->temporaryTables[$originalTable] = $this->createTemporaryTable($originalTable); } return $this->temporaryTables[$originalTable]; } /** * @inheritDoc */ public function swapIndexTables(array $originalTablesNames) { $toRename = []; /** @var string[] $toDrop */ $toDrop = []; /** @var string[] $temporaryTablesRenamed */ $temporaryTablesRenamed = []; $restoreTriggerQueries = []; //Renaming temporary tables to original tables' names, dropping old //tables. foreach ($originalTablesNames as $tableName) { $tableName = $this->resourceConnection->getTableName($tableName); $temporaryOriginalName = $this->resourceConnection->getTableName( $tableName . $this->generateRandomSuffix() ); $temporaryTableName = $this->getWorkingTableName($tableName); $restoreTriggerQueries[] = $this->getRestoreTriggerQueries($tableName); $toRename[] = [ 'oldName' => $tableName, 'newName' => $temporaryOriginalName, ]; $toRename[] = [ 'oldName' => $temporaryTableName, 'newName' => $tableName, ]; $toDrop[] = $temporaryOriginalName; $temporaryTablesRenamed[] = $tableName; } //Swapping tables. $this->resourceConnection->getConnection()->renameTablesBatch($toRename); //Cleaning up. foreach ($temporaryTablesRenamed as $tableName) { unset($this->temporaryTables[$tableName]); } //Removing old ones. foreach ($toDrop as $tableName) { $this->resourceConnection->getConnection()->dropTable($tableName); } //Restoring triggers $restoreTriggerQueries = array_merge([], ...$restoreTriggerQueries); foreach ($restoreTriggerQueries as $restoreTriggerQuery) { $this->resourceConnection->getConnection()->multiQuery($restoreTriggerQuery); } } /** * Get queries for table triggers restoring. * * @param string $tableName * @return array */ private function getRestoreTriggerQueries(string $tableName): array { $triggers = $this->resourceConnection->getConnection() ->query('SHOW TRIGGERS LIKE \''. $tableName . '\'') ->fetchAll(); if (!$triggers) { return []; } $result = []; foreach ($triggers as $trigger) { // phpcs:ignore Magento2.SQL.RawQuery.FoundRawSql $result[] = 'DROP TRIGGER IF EXISTS ' . $trigger['Trigger']; $triggerData = $this->resourceConnection->getConnection() ->query('SHOW CREATE TRIGGER '. $trigger['Trigger']) ->fetch(); $result[] = preg_replace('/DEFINER=[^\s]*/', '', $triggerData['SQL Original Statement']); } return $result; } /** * Cleanup leftover temporary tables */ public function __destruct() { foreach ($this->temporaryTables as $tableName) { $this->resourceConnection->getConnection()->dropTable($tableName); } } }