72 $this->_productIndexerHelper = $productIndexerHelper;
74 $this->_connection =
$resource->getConnection();
77 $this->_tableData = $tableData;
90 public function build(
$storeId, $changedIds, $valueFieldSuffix, $tableDropSuffix, $fillTmpTables)
92 $attributes = $this->_productIndexerHelper->getAttributes();
93 $eavAttributes = $this->_productIndexerHelper->getTablesStructure(
$attributes);
95 $this->_createTemporaryFlatTable(
$storeId);
100 $this->_updateTemporaryTableByStoreValues($eavAttributes, $changedIds,
$storeId, $valueFieldSuffix);
103 $flatTable = $this->_productIndexerHelper->getFlatTableName(
$storeId);
104 $flatDropName = $flatTable . $tableDropSuffix;
106 $this->_productIndexerHelper->getFlatTableName(
$storeId)
108 $this->_tableData->move($flatTable, $flatDropName, $temporaryFlatTableName);
120 protected function _createTemporaryFlatTable(
$storeId)
122 $columns = $this->_productIndexerHelper->getFlatColumns();
124 $indexesNeed = $this->_productIndexerHelper->getFlatIndexes();
126 $maxIndex = $this->_config->getValue(
127 self::XML_NODE_MAX_INDEX_COUNT
129 if ($maxIndex && count($indexesNeed) > $maxIndex) {
130 throw new \Magento\Framework\Exception\LocalizedException(
132 'The Flat Catalog module has a limit of %2$d filterable and/or sortable attributes.' 133 .
'Currently there are %1$d of them.' 134 .
'Please reduce the number of filterable/sortable attributes in order to use this module',
142 $indexProps = array_values($indexesNeed);
143 $upperPrimaryKey = strtoupper(\
Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_PRIMARY);
144 foreach ($indexProps as
$i => $indexProp) {
145 $indexName = $this->_connection->getIndexName(
147 $indexProp[
'fields'],
150 $indexProp[
'type'] = strtoupper($indexProp[
'type']);
151 if ($indexProp[
'type'] == $upperPrimaryKey) {
152 $indexKey = $upperPrimaryKey;
154 $indexKey = $indexName;
158 'KEY_NAME' => $indexName,
159 'COLUMNS_LIST' => $indexProp[
'fields'],
160 'INDEX_TYPE' => strtolower($indexProp[
'type']),
162 $indexKeys[
$i] = $indexKey;
164 $indexesNeed = array_combine($indexKeys, $indexProps);
167 $table = $this->_connection->newTable(
170 foreach (
$columns as $fieldName => $fieldProp) {
171 $columnLength = isset($fieldProp[
'length']) ? $fieldProp[
'length'] :
null;
173 $columnDefinition = [
174 'nullable' => isset($fieldProp[
'nullable']) ? (bool)$fieldProp[
'nullable'] :
false,
175 'unsigned' => isset($fieldProp[
'unsigned']) ? (bool)$fieldProp[
'unsigned'] :
false,
176 'default' => isset($fieldProp[
'default']) ? $fieldProp[
'default'] :
false,
180 $columnComment = isset($fieldProp[
'comment']) ? $fieldProp[
'comment'] : $fieldName;
182 if ($fieldName ==
'created_at') {
183 $columnDefinition[
'nullable'] =
true;
184 $columnDefinition[
'default'] =
null;
187 $table->addColumn($fieldName, $fieldProp[
'type'], $columnLength, $columnDefinition, $columnComment);
190 foreach ($indexesNeed as $indexProp) {
192 $indexProp[
'KEY_NAME'],
193 $indexProp[
'COLUMNS_LIST'],
194 [
'type' => $indexProp[
'INDEX_TYPE']]
198 $table->setComment(
"Catalog Product Flat (Store {$storeId})");
200 $this->_connection->dropTable(
203 $this->_connection->createTable(
$table);
216 $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
217 $select = $this->_connection->select();
219 $this->_productIndexerHelper->getFlatTableName(
$storeId)
221 $flatColumns = $this->_productIndexerHelper->getFlatColumns();
222 $entityTableName = $this->_productIndexerHelper->getTable(
'catalog_product_entity');
224 $columnsList = array_keys($tables[$entityTableName]);
227 unset($tables[$entityTableName]);
229 $allColumns = array_values(
231 array_merge([
'entity_id', $linkField,
'type_id',
'attribute_set_id'], $columnsList)
236 $status = $this->_productIndexerHelper->getAttribute(
'status');
238 $statusConditions = [
239 sprintf(
'e.%s = dstatus.%s', $linkField, $linkField),
240 'dstatus.store_id = ' . (int)
$storeId,
241 'dstatus.attribute_id = ' . (
int)
$status->getId(),
243 $statusExpression = $this->_connection->getIfNullSql(
245 $this->_connection->quoteIdentifier(
"{$statusTable}.status")
249 [
'et' => $entityTemporaryTableName],
252 [
'e' => $this->resource->getTableName(
'catalog_product_entity')],
253 'e.entity_id = et.entity_id',
256 [
'wp' => $this->_productIndexerHelper->getTable(
'catalog_product_website')],
257 'wp.product_id = e.entity_id AND wp.website_id = ' .
$websiteId,
260 [
'dstatus' =>
$status->getBackend()->getTable()],
261 implode(
' AND ', $statusConditions),
268 $columnValueNames = [];
270 $temporaryValueTableName = $temporaryTableName . $valueFieldSuffix;
271 $columnsNames = array_keys(
$columns);
275 sprintf(
'e.%1$s = %2$s.%1$s', $linkField, $temporaryTableName),
278 $allColumns = array_merge($allColumns, $columnsNames);
280 foreach ($columnsNames as
$name) {
281 $columnValueName =
$name . $valueFieldSuffix;
282 if (isset($flatColumns[$columnValueName])) {
283 $columnValueNames[] = $columnValueName;
286 if (!empty($columnValueNames)) {
288 $temporaryValueTableName,
289 sprintf(
'e.%1$s = %2$s.%1$s', $linkField, $temporaryValueTableName),
292 $allColumns = array_merge($allColumns, $columnValueNames);
295 $sql =
$select->insertFromSelect($temporaryFlatTableName, $allColumns,
false);
296 $this->_connection->query($sql);
308 protected function _updateTemporaryTableByStoreValues(
314 $flatColumns = $this->_productIndexerHelper->getFlatColumns();
316 $this->_productIndexerHelper->getFlatTableName(
$storeId)
318 $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
323 if (
$attribute->getBackend()->getType() !=
'static') {
324 $joinCondition = sprintf(
't.%s = e.%s', $linkField, $linkField) .
325 ' AND t.attribute_id=' .
327 ' AND t.store_id = ' .
329 ' AND t.value IS NOT NULL';
331 $select = $this->_connection->select()
333 [
'e' => $this->resource->getTableName(
'catalog_product_entity')],
334 'e.entity_id = et.entity_id',
341 if (!empty($changedIds)) {
342 $select->where($this->_connection->quoteInto(
'et.entity_id IN (?)', $changedIds));
344 $sql =
$select->crossUpdateFromSelect([
'et' => $temporaryFlatTableName]);
345 $this->_connection->query($sql);
350 $select = $this->_connection->select()->joinInner(
351 [
't' => $this->_productIndexerHelper->getTable(
'eav_attribute_option_value')],
355 if (!empty($changedIds)) {
356 $select->where($this->_connection->quoteInto(
'et.entity_id IN (?)', $changedIds));
358 $sql =
$select->crossUpdateFromSelect([
'et' => $temporaryFlatTableName]);
359 $this->_connection->query($sql);
379 private function getMetadataPool()
381 if (
null === $this->metadataPool) {
383 ->get(\
Magento\Framework\EntityManager\MetadataPool::class);
_fillTemporaryFlatTable(array $tables, $storeId, $valueFieldSuffix)
__construct(\Magento\Catalog\Helper\Product\Flat\Indexer $productIndexerHelper, \Magento\Framework\App\ResourceConnection $resource, \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Catalog\Model\Indexer\Product\Flat\TableDataInterface $tableData)
const XML_NODE_MAX_INDEX_COUNT
_getTemporaryTableName($tableName)
build($storeId, $changedIds, $valueFieldSuffix, $tableDropSuffix, $fillTmpTables)
if(!isset($_GET['name'])) $name