Как создать mysql триггер с помощью инсталлятора

[10 ноября 2016 г.]    Российская сборка Magento 2.49.12
Magento 2: модули и услуги
#1 Ярослав Федорук
  • Группа: Пользователь
  • Сообщений: 26
  • Регистрация: 23.01.2011

06.12.2011 17:28

Можно ли вообще прописать в инсталлятор создание mysql триггера? Если да, то как это корректно сделать?

#2 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

06.12.2011 17:38

Что вы называете термином «инсталлятор»?

#3 Ярослав Федорук
  • Группа: Пользователь
  • Сообщений: 26
  • Регистрация: 23.01.2011

07.12.2011 11:12

Имею ввиду инсталляторы модулей. Например все файлы из app/code/core/Mage/Catalog/sql/catalog_setup которые создают нужные таблицы для модуля Catalog. Создание триггера таким способом

Цитата

/* @var $installer Mage_Catalog_Model_Resource_Eav_Mysql4_Setup */
$installer = $this;
$installer->startSetup();
$installer->run("
CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`
FOR EACH ROW BEGIN
insert into `test_tbl2` SET id = 1;
END;
");
$installer->endSetup();


приводит к ошибке, хотя если запустить с консоли, триггер создается.

#4 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

07.12.2011 11:14

Приведите текст диагностического сообщения системы на создание триггера.

#5 Ярослав Федорук
  • Группа: Пользователь
  • Сообщений: 26
  • Регистрация: 23.01.2011

07.12.2011 11:26

Цитата

PDOException Object
(
[message:protected] => SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3
[string:Exception:private] =>
[code:protected] => 42000
[file:protected] => /www/magento.net/lib/Varien/Db/Adapter/Pdo/Mysql.php
[line:protected] => 276
[trace:Exception:private] => Array
(
[0] => Array
(
[file] => /www/magento.net/lib/Varien/Db/Adapter/Pdo/Mysql.php
[line] => 276
[function] => query
[class] => PDO
[type] => ->
[args] => Array
(
[0] => CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`
FOR EACH ROW BEGIN
insert into `test_tbl2` SET id = 1
)

)

[1] => Array
(
[file] => /www/magento.net/lib/Varien/Db/Adapter/Pdo/Mysql.php
[line] => 397
[function] => raw_query
[class] => Varien_Db_Adapter_Pdo_Mysql
[type] => ->
[args] => Array
(
[0] => CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`
FOR EACH ROW BEGIN
insert into `test_tbl2` SET id = 1
)

)

[2] => Array
(
[file] => /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php
[line] => 636
[function] => multi_query
[class] => Varien_Db_Adapter_Pdo_Mysql
[type] => ->
[args] => Array
(
[0] =>
CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`
FOR EACH ROW BEGIN
insert into `test_tbl2` SET id = 1;
END;

)

)

[3] => Array
(
[file] => /www/magento.net/app/code/local/Test/LikeProduct/sql/likeproduct_setup/mysql4-install-0.1.0.php
[line] => 46
[function] => run
[class] => Mage_Core_Model_Resource_Setup
[type] => ->
[args] => Array
(
[0] =>
CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`
FOR EACH ROW BEGIN
insert into `test_tbl2` SET id = 1;
END;

)

)

[4] => Array
(
[file] => /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php
[line] => 376
[args] => Array
(
[0] => /www/magento.net/app/code/local/Test/LikeProduct/sql/likeproduct_setup/mysql4-install-0.1.0.php
)

[function] => include
)

[5] => Array
(
[file] => /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php
[line] => 276
[function] => _modifyResourceDb
[class] => Mage_Core_Model_Resource_Setup
[type] => ->
[args] => Array
(
[0] => install
[1] =>
[2] => 0.1.1
)

)

[6] => Array
(
[file] => /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php
[line] => 240
[function] => _installResourceDb
[class] => Mage_Core_Model_Resource_Setup
[type] => ->
[args] => Array
(
[0] => 0.1.1
)

)

[7] => Array
(
[file] => /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php
[line] => 161
[function] => applyUpdates
[class] => Mage_Core_Model_Resource_Setup
[type] => ->
[args] => Array
(
)

)

[8] => Array
(
[file] => /www/magento.net/app/code/core/Mage/Core/Model/App.php
[line] => 363
[function] => applyAllUpdates
[class] => Mage_Core_Model_Resource_Setup
[type] => ::
[args] => Array
(
)

)

[9] => Array
(
[file] => /www/magento.net/app/code/core/Mage/Core/Model/App.php
[line] => 295
[function] => _initModules
[class] => Mage_Core_Model_App
[type] => ->
[args] => Array
(
)

)

[10] => Array
(
[file] => /www/magento.net/app/Mage.php
[line] => 596
[function] => run
[class] => Mage_Core_Model_App
[type] => ->
[args] => Array
(
[0] => Array
(
[scope_code] =>
[scope_type] => store
[options] => Array
(
)

)

)

)

[11] => Array
(
[file] => /www/magento.net/index.php
[line] => 108
[function] => run
[class] => Mage
[type] => ::
[args] => Array
(
)

)

)

[previous:Exception:private] =>
[errorInfo] => Array
(
[0] => 42000
[1] => 1064
[2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3
)

)

Error in file: "/www/magento.net/app/code/local/Test/LikeProduct/sql/likeproduct_setup/mysql4-install-0.1.0.php" - SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3

#0 /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php(390): Mage::exception('Mage_Core', 'Error in file: ...')
#1 /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php(276): Mage_Core_Model_Resource_Setup->_modifyResourceDb('install', '', '0.1.1')
#2 /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php(240): Mage_Core_Model_Resource_Setup->_installResourceDb('0.1.1')
#3 /www/magento.net/app/code/core/Mage/Core/Model/Resource/Setup.php(161): Mage_Core_Model_Resource_Setup->applyUpdates()
#4 /www/magento.net/app/code/core/Mage/Core/Model/App.php(363): Mage_Core_Model_Resource_Setup::applyAllUpdates()
#5 /www/magento.net/app/code/core/Mage/Core/Model/App.php(295): Mage_Core_Model_App->_initModules()
#6 /www/magento.net/app/Mage.php(596): Mage_Core_Model_App->run(Array)
#7 /www/magento.net/index.php(108): Mage::run()
#8 {main}


#6 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

07.12.2011 11:30

Обладает ли учётная запись Magento для MySQL привилегией SUPER?

#7 Ярослав Федорук
  • Группа: Пользователь
  • Сообщений: 26
  • Регистрация: 23.01.2011

07.12.2011 11:35

Да, конечно. Учетная запись root. Под ней с консоли все без ошибок создается.

#8 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

07.12.2011 11:36

Какова версия сервера MySQL?

#9 Ярослав Федорук
  • Группа: Пользователь
  • Сообщений: 26
  • Регистрация: 23.01.2011

07.12.2011 11:40

Server version: 5.5.16
Единственное что различно, это с консоли добаляю еще DELIMITER. Но если его прописать в инсталлятор, то ошибка выскочит уже на слове DELIMITER. Да и насколько я знаю для PDO не нужно указывать делимитеры.

#10 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

07.12.2011 11:42

Ваш запрос некорректен, даже если его просто выполнить через phpMyAdmin (разумеется, создав предварительно упомянутые в запросе таблицы и столбцы).
Так что причина - в запросе.

#11 Ярослав Федорук
  • Группа: Пользователь
  • Сообщений: 26
  • Регистрация: 23.01.2011

07.12.2011 11:46

а как же быть с консолью?

Цитата

mysql> create table test_tbl (
-> `id` int(10) unsigned DEFAULT NULL);
Query OK, 0 rows affected (0.12 sec)

mysql>
mysql>
mysql> create table test_tbl2 ( `id` int(10) unsigned DEFAULT NULL);
Query OK, 0 rows affected (0.12 sec)

mysql>
mysql>
mysql> DELIMITER |
mysql> CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`
-> FOR EACH ROW BEGIN
-> insert into `test_tbl2` SET id = 1;
-> END;
-> |
Query OK, 0 rows affected (0.07 sec)

mysql> DELIMITER ;
mysql>
mysql>
mysql> show triggers;
+--------------+--------+----------+-----------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
| Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation |
+--------------+--------+----------+-----------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
| test_trigger | INSERT | test_tbl | BEGIN
insert into `test_tbl2` SET id = 1;
END | AFTER | NULL | | root@localhost | latin1 | latin1_swedish_ci | latin1_swedish_ci |
+--------------+--------+----------+-----------------------------------------------+--------+---------+----------+----------------+----------------------+----------------------+--------------------+
1 row in set (0.01 sec)

mysql> exit

Попробуйте с консоли, все корректно создается.

#12 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

07.12.2011 11:48

Вы уже манипулируете фактами.
Указанный вами сейчас запрос не равнозначен запросу из третьего сообщения темы.

#13 Ярослав Федорук
  • Группа: Пользователь
  • Сообщений: 26
  • Регистрация: 23.01.2011

07.12.2011 11:58

Простите, может я где-то ошибся,

Цитата

$installer->run("
CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`
FOR EACH ROW BEGIN
insert into `test_tbl2` SET id = 1;
END;
");

И вот запрос выполненный из консоли.

Цитата

mysql> DELIMITER |
mysql> CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`
-> FOR EACH ROW BEGIN
-> insert into `test_tbl2` SET id = 1;
-> END;
-> |
Query OK, 0 rows affected (0.07 sec)


Запросы вроде одинаковые. О делимитерах я тоже упоминал. Честно не совсем понимаю где несоответсвтие, но это вообще говоря не так и принципиально, мне бы просто рабочий пример самого элементарного триггера который бы создавался при установке модуля. Где-то я видимо ошибаюсь, но не могу понять где. С примером уже бы и сам разобрался, но гугление ничего не дало, вот и спросил поэтому здесь.

#14 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

07.12.2011 12:09

Вот при таком исправлении ваш код будет работать
$installer->run("CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_tbl`FOR EACH ROW insert into `test_tbl2` SET id = 1");


Такой запрос точь-в-точь соотствует вашей потребности из третьего сообщения, и он синтаксически корректен для установщика модуля.
Если же вам потом потребуется написать другой, многострочный триггер, то читайте, как посредством PDO выполнять многострочные запросы.
Вообще же, использование триггеров в тиражируемых модулях для Magento - это неверное, в корне ошибочное архитектурное решение, потому что магазины ваших клиентов при подключении к MySQL могут не обладать привилегией SUPER.

#15 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

07.12.2011 12:17

Более того, триггеры появились только в MySQL начиная с версии 5.
Однако ядро Magento совместимо с MySQL 4, и именно MySQL 4 является официальным требованием Magento.
Вставляя триггер в тиражируемый модуль для Magento, программист должен быть готов к тому, что у многих потенциальных клиентов, у которых стоит MySQL 4, модуль работать не будет.

#16 Ярослав Федорук
  • Группа: Пользователь
  • Сообщений: 26
  • Регистрация: 23.01.2011

07.12.2011 12:36

Дмитрий, спасибо большое за помощь! Да, все работает. Хотя бы понятно уже что дело в многострочности.
Конечно Вы правы, триггеры не лучшее решение, но иногда очень удобные, для взаимосвязей между таблицами. К сожалению внешние ключи довольно ограничены в этом плане. Жаль, что по различным "не программистским" :) причинам во многих случаях приходится отказываться от удобных инструментов. Но даже в таком случае на будущее я думаю это будет полезным.
Спасибо Вам!

Поделиться темой: