99use Magento \Catalog \Model \Product ;
1010use Magento \Eav \Setup \EavSetup ;
1111use Magento \Eav \Setup \EavSetupFactory ;
12- use Magento \Framework \Exception \ LocalizedException ;
12+ use Magento \Framework \DB \ Adapter \ AdapterInterface ;
1313use Magento \Framework \Setup \ModuleDataSetupInterface ;
1414use Magento \Framework \Setup \Patch \DataPatchInterface ;
15+ use Magento \Framework \Setup \Patch \NonTransactionableInterface ;
1516
16- class UpdateMultiselectAttributesBackendTypes implements DataPatchInterface
17+ class UpdateMultiselectAttributesBackendTypes implements DataPatchInterface, NonTransactionableInterface
1718{
1819 /**
1920 * @var ModuleDataSetupInterface
@@ -24,6 +25,11 @@ class UpdateMultiselectAttributesBackendTypes implements DataPatchInterface
2425 */
2526 private $ eavSetupFactory ;
2627
28+ /**
29+ * @var array
30+ */
31+ private $ triggersRestoreQueries = [];
32+
2733 /**
2834 * MigrateMultiselectAttributesData constructor.
2935 * @param ModuleDataSetupInterface $dataSetup
@@ -61,6 +67,7 @@ public function apply()
6167 $ this ->dataSetup ->startSetup ();
6268 $ setup = $ this ->dataSetup ;
6369 $ connection = $ setup ->getConnection ();
70+ $ this ->triggersRestoreQueries = [];
6471
6572 $ attributeTable = $ setup ->getTable ('eav_attribute ' );
6673 /** @var EavSetup $eavSetup */
@@ -74,26 +81,31 @@ public function apply()
7481 ->where ('backend_type = ? ' , 'varchar ' )
7582 ->where ('frontend_input = ? ' , 'multiselect ' )
7683 );
84+ $ attributesToMigrate = array_map ('intval ' , $ attributesToMigrate );
7785
7886 $ varcharTable = $ setup ->getTable ('catalog_product_entity_varchar ' );
7987 $ textTable = $ setup ->getTable ('catalog_product_entity_text ' );
80- $ varcharTableDataSql = $ connection
81- ->select ()
82- ->from ($ varcharTable )
83- ->where ('attribute_id in (?) ' , $ attributesToMigrate );
8488
8589 $ columns = $ connection ->describeTable ($ varcharTable );
8690 unset($ columns ['value_id ' ]);
87- $ connection ->query (
88- $ connection ->insertFromSelect (
89- $ connection ->select ()
90- ->from ($ varcharTable , array_keys ($ columns ))
91- ->where ('attribute_id in (?) ' , $ attributesToMigrate ),
92- $ textTable ,
93- array_keys ($ columns )
94- )
95- );
96- $ connection ->query ($ connection ->deleteFromSelect ($ varcharTableDataSql , $ varcharTable ));
91+ $ this ->dropTriggers ($ textTable );
92+ $ this ->dropTriggers ($ varcharTable );
93+ try {
94+ $ connection ->query (
95+ $ connection ->insertFromSelect (
96+ $ connection ->select ()
97+ ->from ($ varcharTable , array_keys ($ columns ))
98+ ->where ('attribute_id in (?) ' , $ attributesToMigrate , \Zend_Db::INT_TYPE ),
99+ $ textTable ,
100+ array_keys ($ columns ),
101+ AdapterInterface::INSERT_ON_DUPLICATE
102+ )
103+ );
104+ $ connection ->delete ($ varcharTable , ['attribute_id IN (?) ' => $ attributesToMigrate ]);
105+ } finally {
106+ $ this ->restoreTriggers ($ textTable );
107+ $ this ->restoreTriggers ($ varcharTable );
108+ }
97109
98110 foreach ($ attributesToMigrate as $ attributeId ) {
99111 $ eavSetup ->updateAttribute ($ entityTypeId , $ attributeId , 'backend_type ' , 'text ' );
@@ -103,4 +115,48 @@ public function apply()
103115
104116 return $ this ;
105117 }
118+
119+ /**
120+ * Drop table triggers
121+ *
122+ * @param string $tableName
123+ * @return void
124+ * @throws \Zend_Db_Statement_Exception
125+ */
126+ private function dropTriggers (string $ tableName ): void
127+ {
128+ $ triggers = $ this ->dataSetup ->getConnection ()
129+ ->query ('SHOW TRIGGERS LIKE \'' . $ tableName . '\'' )
130+ ->fetchAll ();
131+
132+ if (!$ triggers ) {
133+ return ;
134+ }
135+
136+ foreach ($ triggers as $ trigger ) {
137+ $ triggerData = $ this ->dataSetup ->getConnection ()
138+ ->query ('SHOW CREATE TRIGGER ' . $ trigger ['Trigger ' ])
139+ ->fetch ();
140+ $ this ->triggersRestoreQueries [$ tableName ][] =
141+ preg_replace ('/DEFINER=[^\s]*/ ' , '' , $ triggerData ['SQL Original Statement ' ]);
142+ // phpcs:ignore Magento2.SQL.RawQuery.FoundRawSql
143+ $ this ->dataSetup ->getConnection ()->query ('DROP TRIGGER IF EXISTS ' . $ trigger ['Trigger ' ]);
144+ }
145+ }
146+
147+ /**
148+ * Restore table triggers.
149+ *
150+ * @param string $tableName
151+ * @return void
152+ * @throws \Zend_Db_Statement_Exception
153+ */
154+ private function restoreTriggers (string $ tableName ): void
155+ {
156+ if (array_key_exists ($ tableName , $ this ->triggersRestoreQueries )) {
157+ foreach ($ this ->triggersRestoreQueries [$ tableName ] as $ query ) {
158+ $ this ->dataSetup ->getConnection ()->multiQuery ($ query );
159+ }
160+ }
161+ }
106162}
0 commit comments