123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\DB;
- use Magento\Framework\DB\Adapter\AdapterInterface;
- /**
- * Class TemporaryTableService creates a temporary table in mysql from a Magento\Framework\DB\Select.
- * Use this class to create an index with that you want to query later for quick data access
- *
- * @api
- * @since 100.1.8
- */
- class TemporaryTableService
- {
- const INDEX_METHOD_HASH = 'HASH';
- const DB_ENGINE_INNODB = 'INNODB';
- /**
- * @var string[]
- */
- private $allowedIndexMethods;
- /**
- * @var string[]
- */
- private $allowedEngines;
- /**
- * @var \Magento\Framework\Math\Random
- */
- private $random;
- /**
- * @var AdapterInterface[]
- */
- private $createdTableAdapters = [];
- /**
- * @param \Magento\Framework\Math\Random $random
- * @param string[] $allowedIndexMethods
- * @param string[] $allowedEngines
- */
- public function __construct(
- \Magento\Framework\Math\Random $random,
- $allowedIndexMethods = [],
- $allowedEngines = []
- ) {
- $this->random = $random;
- $this->allowedIndexMethods = $allowedIndexMethods;
- $this->allowedEngines = $allowedEngines;
- }
- /**
- * Creates a temporary table from select removing duplicate rows if you have a union in your select
- * This method should always be paired with dropTable to ensure cleanup
- * Make sure you index your data so you can query it fast
- * You can choose from memory or file table and provide indexes to ensure fast data query
- *
- * Example: createFromSelect(
- * $selectObject,
- * $this->resourceConnection->getConnection(),
- * [
- * 'PRIMARY' => ['primary_id'],
- * 'some_single_field_index' => ['field'],
- * 'UNQ_some_multiple_field_index' => ['field1', 'field2'],
- * ]
- * )
- * Note that indexes names with UNQ_ prefix, will be created as unique
- *
- * @param Select $select
- * @param AdapterInterface $adapter
- * @param array $indexes
- * @param string $indexMethod
- * @param string $dbEngine
- * @return string
- * @throws \InvalidArgumentException
- * @since 100.1.8
- */
- public function createFromSelect(
- Select $select,
- AdapterInterface $adapter,
- array $indexes = [],
- $indexMethod = self::INDEX_METHOD_HASH,
- $dbEngine = self::DB_ENGINE_INNODB
- ) {
- if (!in_array($indexMethod, $this->allowedIndexMethods)) {
- throw new \InvalidArgumentException(
- sprintf('indexMethod must be one of %s', implode(',', $this->allowedIndexMethods))
- );
- }
- if (!in_array($dbEngine, $this->allowedEngines)) {
- throw new \InvalidArgumentException(
- sprintf('dbEngine must be one of %s', implode(',', $this->allowedEngines))
- );
- }
- $name = $this->random->getUniqueHash('tmp_select_');
- $indexStatements = [];
- foreach ($indexes as $indexName => $columns) {
- $renderedColumns = implode(',', array_map([$adapter, 'quoteIdentifier'], $columns));
- $indexType = sprintf(
- 'INDEX %s USING %s',
- $adapter->quoteIdentifier($indexName),
- $indexMethod
- );
- if ($indexName === 'PRIMARY') {
- $indexType = 'PRIMARY KEY';
- } elseif (strpos($indexName, 'UNQ_') === 0) {
- $indexType = sprintf('UNIQUE %s', $adapter->quoteIdentifier($indexName));
- }
- $indexStatements[] = sprintf('%s(%s)', $indexType, $renderedColumns);
- }
- $statement = sprintf(
- 'CREATE TEMPORARY TABLE %s %s ENGINE=%s IGNORE (%s)',
- $adapter->quoteIdentifier($name),
- $indexStatements ? '(' . implode(',', $indexStatements) . ')' : '',
- $adapter->quoteIdentifier($dbEngine),
- "{$select}"
- );
- $adapter->query(
- $statement,
- $select->getBind()
- );
- $this->createdTableAdapters[$name] = $adapter;
- return $name;
- }
- /**
- * Method used to drop a table by name
- * This class will hold all temporary table names in createdTableAdapters array
- * so we can dispose them once we're finished
- *
- * Example: dropTable($name)
- * where $name is a variable that holds the name for a previously created temporary table
- * by using "createFromSelect" method
- *
- * @param string $name
- * @return bool
- * @since 100.1.8
- */
- public function dropTable($name)
- {
- if (!empty($this->createdTableAdapters)) {
- if (isset($this->createdTableAdapters[$name]) && !empty($name)) {
- $adapter = $this->createdTableAdapters[$name];
- $adapter->dropTemporaryTable($name);
- unset($this->createdTableAdapters[$name]);
- return true;
- }
- }
- return false;
- }
- }
|