@@ -183,6 +183,10 @@ class Product extends AbstractEntity
183183
184184 private const ERROR_DUPLICATE_URL_KEY_BY_CATEGORY = 'duplicatedUrlKeyByCategory ' ;
185185
186+ private const STRING_OVERFLOW = 8000 ;
187+
188+ private const STRING_PADDING = 5 ;
189+
186190 /**
187191 * @var array
188192 */
@@ -3166,6 +3170,42 @@ protected function _saveValidatedBunches()
31663170 return parent ::_saveValidatedBunches ();
31673171 }
31683172
3173+ /**
3174+ * Split SKUs into butches
3175+ *
3176+ * @param array $data
3177+ * @return array
3178+ */
3179+ private function splitIntoBatches (array $ data ): array
3180+ {
3181+ $ batches = [];
3182+ $ batch = [];
3183+ $ accumulatedSkuLength = 0 ;
3184+ $ accumulatedUrlLength = 0 ;
3185+ foreach ($ data as $ url => $ sku ) {
3186+ $ skuLength = strlen ($ sku ) + self ::STRING_PADDING ;
3187+ $ urlLength = strlen ($ url ) + self ::STRING_PADDING ;
3188+ if ($ skuLength + $ accumulatedSkuLength >= self ::STRING_OVERFLOW ||
3189+ $ urlLength + $ accumulatedUrlLength >= self ::STRING_OVERFLOW
3190+ ) {
3191+ $ batches [] = $ batch ;
3192+ $ batch = [$ url => $ sku ];
3193+ $ accumulatedSkuLength = $ skuLength ;
3194+ $ accumulatedUrlLength = $ urlLength ;
3195+ } else {
3196+ $ batch [$ url ] = $ sku ;
3197+ $ accumulatedSkuLength += $ skuLength ;
3198+ $ accumulatedUrlLength += $ urlLength ;
3199+ }
3200+ }
3201+
3202+ if (!empty ($ batch )) {
3203+ $ batches [] = $ batch ;
3204+ }
3205+
3206+ return $ batches ;
3207+ }
3208+
31693209 /**
31703210 * Check that url_keys are not already assigned to others entities in DB
31713211 *
@@ -3176,21 +3216,27 @@ protected function checkUrlKeyDuplicates()
31763216 {
31773217 $ resource = $ this ->getResource ();
31783218 foreach ($ this ->urlKeys as $ storeId => $ urlKeys ) {
3179- $ urlKeyDuplicates = $ this ->_connection ->fetchAssoc (
3180- $ this ->_connection ->select ()->from (
3181- ['url_rewrite ' => $ resource ->getTable ('url_rewrite ' )],
3182- [
3183- 'request_path ' ,
3184- 'store_id ' ,
3185- 'entity_type '
3186- ]
3187- )->joinLeft (
3188- ['cpe ' => $ resource ->getTable ('catalog_product_entity ' )],
3189- "cpe.entity_id = url_rewrite.entity_id "
3190- )->where ('request_path IN (?) ' , array_map ('strval ' , array_keys ($ urlKeys )))
3191- ->where ('store_id IN (?) ' , $ storeId )
3192- ->where ('cpe.sku not in (?) ' , array_values ($ urlKeys ))
3193- );
3219+ $ requestPaths = $ this ->splitIntoBatches ($ urlKeys );
3220+
3221+ $ urlKeyDuplicates = [];
3222+ foreach ($ requestPaths as $ urlKeys ) {
3223+ $ duplicates = $ this ->_connection ->fetchAssoc (
3224+ $ this ->_connection ->select ()->from (
3225+ ['url_rewrite ' => $ resource ->getTable ('url_rewrite ' )],
3226+ [
3227+ 'request_path ' ,
3228+ 'store_id ' ,
3229+ 'entity_type '
3230+ ]
3231+ )->joinLeft (
3232+ ['cpe ' => $ resource ->getTable ('catalog_product_entity ' )],
3233+ "cpe.entity_id = url_rewrite.entity_id "
3234+ )->where ('request_path IN (?) ' , array_map ('strval ' , array_keys ($ urlKeys )))
3235+ ->where ('store_id IN (?) ' , $ storeId )
3236+ ->where ('cpe.sku not in (?) ' , array_values ($ urlKeys ))
3237+ );
3238+ $ urlKeyDuplicates = [...$ urlKeyDuplicates , ...$ duplicates ];
3239+ }
31943240
31953241 foreach ($ urlKeyDuplicates as $ entityData ) {
31963242 $ rowNum = $ this ->rowNumbers [$ entityData ['store_id ' ]][$ entityData ['request_path ' ]];
0 commit comments