MySQL - 触发器中通过UDF的动态​​语句

时间:2014-07-09 08:46:04

标签: mysql triggers user-defined-functions

为了绕过触发器中缺少准备好的语句,我试着写一个执行其agrument的UDF。

udf依赖于MySQL C api并使用有限的特定用户。

#include "string"
#include "string.h"
#include "stdio.h"
#include "mysql.h"
#include <sstream>

extern "C" my_bool execsql_init(UDF_INIT* initid, UDF_ARGS* args, char* msg) {
        if (args->arg_count != 1) {
                memcpy(msg, "Missing message argument.", 26);
                return 1;
        }
        if (args->arg_type[0] != STRING_RESULT) {
                args->arg_type[0] = STRING_RESULT;
        }
        return 0;
}

char* setError(unsigned long* length, std::string message) {
        *length = message.size();
        return (char*)message.c_str();
}

extern "C" char* execsql(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length, my_bool* is_null, my_bool* error) {
        MYSQL *con = mysql_init(NULL);
        if (con == NULL) {
                return setError(length, "Erreur d'initialisation");
        }

        if (mysql_real_connect(con, "172.31.72.6", "execsqluser", "qwerty", "nvannuaire", 0, NULL, 0) == NULL) {
                mysql_close(con);
                return setError(length, "Erreur de connexion");
        }

        mysql_query(con, "use nvannuaire;");

        if (mysql_query(con, args->args[0])) {
                std::ostringstream ss;
                ss << mysql_errno(con) << ": " << mysql_error(con);
                std::string error = ss.str();
                return setError(length, (char*)error.c_str());
                mysql_close(con);
        }

        mysql_close(con);

        std::string retour = "ok !";
        *length = retour.size();
        return (char*)retour.c_str();

}

这似乎运作良好,但出现问题。 在调用execsql()之后,没有其他事情发生。 该语句将被执行,但不会执行存储过程中的下一个语句。

SELECT execsql(statement_requete) INTO i_retour FROM t_requete WHERE id_requete = a_id_requete;

-- test la valeur de retour
IF i_retour != 'ok !' THEN
    -- si pas ok, on renseigne l'erreur via update
    UPDATE t_requete SET erreur_requete = i_retour WHERE id_requete = a_id_requete;
ELSE
    -- si == 'ok !', on delete
    DELETE FROM t_requete WHERE id_requete = a_id_requete;
END IF;

dbForge Studio引发了“已超时读取通信包”。

这是mysql.log文件:

.
.
.
140709 10:33:21  2020 Init DB   nvannuaire
                 2020 Query     select * from ta_avancement order by id_tache desc limit 0, 20
140709 10:33:22  2020 Query     select * from t_tache order by id_tache desc limit 0, 20
                 2020 Query     SHOW TABLE STATUS FROM `nvannuaire` LIKE 't_tache'
                 2020 Query     SHOW VARIABLES LIKE 'auto_increment%'
                 2020 Query     select * from t_requete order by id_evenement desc limit 0, 20
                 2020 Query     SHOW TABLE STATUS FROM `nvannuaire` LIKE 't_requete'
                 2020 Query     SHOW VARIABLES LIKE 'auto_increment%'
                 2020 Query     select * from t_comptenovell where id_comptenovell = 115 limit 0,1000
                 2020 Query     SHOW TABLE STATUS FROM `nvannuaire` LIKE 't_comptenovell'
                 2020 Query     SHOW VARIABLES LIKE 'auto_increment%'
                 2020 Query     CALL pr_si_avancement_avancer(55, 115, 2)
                 2029 Connect   execsqluser@172.31.72.6 on nvannuaire
                 2029 Query     use nvannuaire
                 2029 Query     UPDATE t_comptenovell SET login_comptenovell = "Test" WHERE id_comptenovell = 115



140709 10:33:52  2020 Init DB   annuaire
140709 10:33:58  2020 Init DB   nvannuaire
                 2020 Query     select * from ta_avancement order by id_tache desc limit 0, 20
                 2020 Query     select * from t_tache order by id_tache desc limit 0, 20
.
.
.

编辑:直接调用execsql函数时,没有错误。它仅在触发器内调用函数时发生。

编辑2:存储引擎是InnoDB。

存储在t_requete中的语句从不适用于t_requete表,但适用于其他表。

经过进一步研究,似乎如果存储在t_requete中的语句包含一些SQL语法错误,则没有超时并且所有过程都成功执行(它将错误存储在t_requete表的erreur_requete中)。 因此,当执行的语句不包含错误以及在触发器内执行时,问题似乎只会发生。

在此测试用例中,触发器在表A后更新。该语句存储在表B中,并在表C上执行更新。

知道为什么会发生这种错误以及如何解决它?

0 个答案:

没有答案