/** * Update relation products * * @param int $storeId * @param int|array $productIds Update child product(s) only * @return \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _updateRelationProducts($storeId, $productIds = null) { if (!$this->_productIndexerHelper->isAddChildData() || !$this->_isFlatTableExists($storeId)) { return $this; } foreach ($this->_getProductTypeInstances() as $typeInstance) { /** @var $typeInstance \Magento\Catalog\Model\Product\Type\AbstractType */ if (!$typeInstance->isComposite(null)) { continue; } $relation = $typeInstance->getRelationInfo(); if ($relation && $relation->getTable() && $relation->getParentFieldName() && $relation->getChildFieldName()) { $columns = $this->_productIndexerHelper->getFlatColumns(); $fieldList = array_keys($columns); unset($columns['entity_id']); unset($columns['child_id']); unset($columns['is_child']); /** @var $select \Magento\Framework\DB\Select */ $select = $this->_connection->select()->from(['t' => $this->_productIndexerHelper->getTable($relation->getTable())], [$relation->getParentFieldName(), $relation->getChildFieldName(), new \Zend_Db_Expr('1')])->join(['e' => $this->_productIndexerHelper->getFlatTableName($storeId)], "e.entity_id = t.{$relation->getChildFieldName()}", array_keys($columns)); if ($relation->getWhere() !== null) { $select->where($relation->getWhere()); } if ($productIds !== null) { $cond = [$this->_connection->quoteInto("{$relation->getChildFieldName()} IN(?)", $productIds), $this->_connection->quoteInto("{$relation->getParentFieldName()} IN(?)", $productIds)]; $select->where(implode(' OR ', $cond)); } $sql = $select->insertFromSelect($this->_productIndexerHelper->getFlatTableName($storeId), $fieldList); $this->_connection->query($sql); } } return $this; }
/** * Apply diff. between 0 store and current store to temporary flat table * * @param array $tables * @param array $changedIds * @param int|string $storeId * @param string $valueFieldSuffix * @return void */ protected function _updateTemporaryTableByStoreValues(array $tables, array $changedIds, $storeId, $valueFieldSuffix) { $flatColumns = $this->_productIndexerHelper->getFlatColumns(); $temporaryFlatTableName = $this->_getTemporaryTableName($this->_productIndexerHelper->getFlatTableName($storeId)); $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); foreach ($tables as $tableName => $columns) { foreach ($columns as $attribute) { /* @var $attribute \Magento\Eav\Model\Entity\Attribute */ $attributeCode = $attribute->getAttributeCode(); if ($attribute->getBackend()->getType() != 'static') { $joinCondition = sprintf('t.%s = e.%s', $linkField, $linkField) . ' AND t.attribute_id=' . $attribute->getId() . ' AND t.store_id = ' . $storeId . ' AND t.value IS NOT NULL'; /** @var $select \Magento\Framework\DB\Select */ $select = $this->_connection->select()->joinInner(['t' => $tableName], $joinCondition, [$attributeCode => 't.value']); if (!empty($changedIds)) { $select->where($this->_connection->quoteInto('e.entity_id IN (?)', $changedIds)); } $sql = $select->crossUpdateFromSelect(['e' => $temporaryFlatTableName]); $this->_connection->query($sql); } //Update not simple attributes (eg. dropdown) if (isset($flatColumns[$attributeCode . $valueFieldSuffix])) { $select = $this->_connection->select()->joinInner(['t' => $this->_productIndexerHelper->getTable('eav_attribute_option_value')], 't.option_id = e.' . $attributeCode . ' AND t.store_id=' . $storeId, [$attributeCode . $valueFieldSuffix => 't.value']); if (!empty($changedIds)) { $select->where($this->_connection->quoteInto('e.entity_id IN (?)', $changedIds)); } $sql = $select->crossUpdateFromSelect(['e' => $temporaryFlatTableName]); $this->_connection->query($sql); } } } }
/** * Move data from temporary tables to flat * * @param string $flatTable * @param string $flatDropName * @param string $temporaryFlatTableName * @return void */ public function move($flatTable, $flatDropName, $temporaryFlatTableName) { $connection = $this->_resource->getConnection(); if (!$connection->isTableExists($flatTable)) { $connection->dropTable($flatDropName); $connection->renameTablesBatch([['oldName' => $temporaryFlatTableName, 'newName' => $flatTable]]); $connection->dropTable($flatDropName); } else { $describe = $connection->describeTable($flatTable); $columns = $this->_productIndexerHelper->getFlatColumns(); $columns = array_keys(array_intersect_key($describe, $columns)); $select = $connection->select(); $select->from(['tf' => sprintf('%s_tmp_indexer', $flatTable)], $columns); $sql = $select->insertFromSelect($flatTable, $columns); $connection->query($sql); $connection->dropTable(sprintf('%s_tmp_indexer', $flatTable)); } }
/** * Fill temporary table by data from products EAV attributes by type * * @param string $tableName * @param array $tableColumns * @param array $changedIds * @param string $valueFieldSuffix * @param int $storeId * @return void */ protected function _fillTemporaryTable($tableName, array $tableColumns, array $changedIds, $valueFieldSuffix, $storeId) { $metadata = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class); if (!empty($tableColumns)) { $columnsChunks = array_chunk($tableColumns, Action\Indexer::ATTRIBUTES_CHUNK_SIZE, true); foreach ($columnsChunks as $columnsList) { $select = $this->_connection->select(); $selectValue = $this->_connection->select(); $entityTableName = $this->_getTemporaryTableName($this->_productIndexerHelper->getTable('catalog_product_entity')); $temporaryTableName = $this->_getTemporaryTableName($tableName); $temporaryValueTableName = $temporaryTableName . $valueFieldSuffix; $keyColumn = ['entity_id']; $columns = array_merge($keyColumn, array_keys($columnsList)); $valueColumns = $keyColumn; $flatColumns = $this->_productIndexerHelper->getFlatColumns(); $iterationNum = 1; $select->from(['et' => $entityTableName], $keyColumn)->join(['e' => $this->resource->getTableName('catalog_product_entity')], 'e.entity_id = et.entity_id', []); $selectValue->from(['e' => $temporaryTableName], $keyColumn); /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ foreach ($columnsList as $columnName => $attribute) { $countTableName = 't' . $iterationNum++; $joinCondition = sprintf('e.%3$s = %1$s.%3$s AND %1$s.attribute_id = %2$d AND %1$s.store_id = 0', $countTableName, $attribute->getId(), $metadata->getLinkField()); $select->joinLeft([$countTableName => $tableName], $joinCondition, [$columnName => 'value']); if ($attribute->getFlatUpdateSelect($storeId) instanceof \Magento\Framework\DB\Select) { $attributeCode = $attribute->getAttributeCode(); $columnValueName = $attributeCode . $valueFieldSuffix; if (isset($flatColumns[$columnValueName])) { $valueJoinCondition = sprintf('e.%1$s = %2$s.option_id AND %2$s.store_id = 0', $attributeCode, $countTableName); $selectValue->joinLeft([$countTableName => $this->_productIndexerHelper->getTable('eav_attribute_option_value')], $valueJoinCondition, [$columnValueName => $countTableName . '.value']); $valueColumns[] = $columnValueName; } } } if (!empty($changedIds)) { $select->where($this->_connection->quoteInto('e.entity_id IN (?)', $changedIds)); } $sql = $select->insertFromSelect($temporaryTableName, $columns, true); $this->_connection->query($sql); if (count($valueColumns) > 1) { if (!empty($changedIds)) { $selectValue->where($this->_connection->quoteInto('e.entity_id IN (?)', $changedIds)); } $sql = $selectValue->insertFromSelect($temporaryValueTableName, $valueColumns, true); $this->_connection->query($sql); } } } }