Can a trigger be temporary ignored in MySQL? - mysql

Say table B has a BEFORE DELETE trigger. However, in some cases, I hope the trigger is disabled when I try to delete something from B, is that possible?

insert a conditional verification (if) inside your trigger to check whether the conditions which will do the actions will be executed or not
e.g:
create trigger ai_eav after insert on eav
for each row begin
set #id=new.entity;
set #attribute=new.attribute;
set #value=new.value;
if n > m then
update pivot set
Author=(select if(#attribute='Author',#value,Author)),
Title=(select if(#attribute='Title',#value,Title)),
Publisher=(select if(#attribute='Publisher',#value,Publisher))
where id=#id;
end if
end
you can find the syntax of mysql if statements here:
http://dev.mysql.com/doc/refman/5.0/en/if.html
this solution is probably much more performatic than deleting and recreating the trigger

For v5.*:
http://www.ehow.com/how_10027479_disable-triggers-mysql.html
Just drop and re-create the trigger.
For v7.0:
http://dev.mysql.com/worklog/task/?id=2825
ALTER TRIGGER ... ENABLE | DISABLE
Implementation in C:
#include <my_global.h>
#include <mysql.h>
#include <string.h>
#define TRIGGER_NAME "testtrigger"
int delete_without_trigger(MYSQL *conn,char *sql) {
if (mysql_query(conn, "SHOW CREATE TRIGGER " TRIGGER_NAME)) {
fprintf(stderr, "%s\n", mysql_error(conn));
return -1;
}
MYSQL_RES *res=mysql_use_result(conn);
MYSQL_ROW row= mysql_fetch_row(res);
char *trigger=strdup(row[2]);
//printf("TRIGGER==============\n%s\n===========\n",trigger);
mysql_free_result(res);
if (mysql_query(conn, "DROP TRIGGER " TRIGGER_NAME)) {
fprintf(stderr, "%s\n", mysql_error(conn));
return -2;
}
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
return -3;
}
if (mysql_query(conn, trigger)) {
fprintf(stderr, "%s\n", mysql_error(conn));
return -4;
}
free(trigger);
return 0;
}//delete_without_trigger
Testing:
int i;
for(i=99;--i>0;) {
printf("%d\n",i);
if(delete_without_trigger(conn,"DELETE FROM syslog WHERE txt='test'")) {
fprintf(stderr, "handling ERROR\n");
exit(1);
}
}

Related

C - alternative using snprintf to prepare MySQL statements?

I've been tearing my hair out for a while on this one. The C code is called from a bash script, which loops through a command's output in a while loop and passes variables to the C script as args. It goes through a list and partitions data properly. I've been using the C MySQL api, and up until now everything has been relatively straight forward. It tries to run a SELECT(EXISTS) command to dictate whether to input a new row, or update an existing one.
I have typed the command into MySQL terminal and it works perfectly. I have even printf'd it and copied the command directly into the terminal. It works....
So why then, am I getting Syntax errors? I've tried escaping fields and input using backticks, single quotes and double quotes and I'm still getting this dumbounding error. I thought maybe it was something to do with the null space? But I'm at my witts end. Here's the code, any advice would be greatly appreciated :)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>
const int MAXLEN = 100;
/* Compile with:
gcc db.connect.c `mysql_config --libs` -O1
for the best results
*/
/* Function definitions for later */
void finish_with_error(MYSQL *con);
int send_query(MYSQL *con, char query[MAXLEN]);
/* If any SQL commands fail, return an error message */
void finish_with_error(MYSQL *con)
{
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(1);
}
/* Helper function to send queries to MySQL database */
int send_query(MYSQL *con, char query[MAXLEN])
{
if (mysql_query(con, query)) {
finish_with_error(con);
}
return 0;
}
int main(int argc, char ** argv)
{
// Establish MySQL API connection, if not- fail with err
MYSQL *con = mysql_init(NULL);
if (con == NULL) {
finish_with_error(con);
}
// Connection string.
if (mysql_real_connect(con, "localhost", "user", "password",
NULL, 0, NULL, 0) == NULL){
finish_with_error(con);
}
if (argv[1] == NULL){
printf("No query passed, terminating script \n");
return 1;
}
if (argv[1] != NULL) {
if( strcmp( argv[1], "--help" ) == 0 ) {
printf("This program was created to interact with MySQL, by checking and updating live network stats\n");
printf("It has 2 parameters, an IP address to look in the database for and a value to update a field by, \
if that IP address is found. ");
printf("If the value is not found, the program will insert a new row.");
return 1;
}
// Works out how much memory to allocate to buffer for snprintf
// Originally cmd_len was 65- as this was the amount of bits needed by the address string.
// This was changed to MAXLEN to prevent SEGFAULTS and give the function breathing room.
size_t cmd_len = MAXLEN;
size_t param_len = sizeof(argv[2]);
size_t q_len = cmd_len + param_len;
// Allocates that memory to a buffer, referenced as query
char *query = malloc(sizeof(char) * q_len);
snprintf(query, q_len, "SELECT EXISTS(SELECT * FROM `analytics`.`live` WHERE `foreign_addr` = `%s`)", argv[1]);
printf("%s\n", query);
send_query(con, query);
free(query);
// Used to store the result of the MySQL select commands
MYSQL_RES *result = mysql_store_result(con);
if (result == NULL) {
finish_with_error(con);
}
// num_fields stores the number of fields, i and x are counters, answer is 1 or 0
int num_fields = mysql_num_fields(result);
int i = 0;
// Loops through each row in the answer statement.
// There will only be one row in the answer, which will be 1 or 0
// Basically, if the IP is found.
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))){
for (i=0; i<num_fields; i++) {
// If the IP isn't in the table
if(!atoi(row[i]))
send_query(con, argv[1]);
// If the IP is already in the table
if(atoi(row[i])) {
snprintf(query, q_len, "UPDATE analytics.live SET count=count+1 WHERE foreign_addr = '%s'", argv[1]);
printf("%s\n", query);
free(query);
snprintf(query, q_len, "UPDATE analytics.live SET dat_sent = dat_sent + %s", argv[2]);
printf("%s\n", query);
free(query);
}
}
}
mysql_close(con);
return 1;
}
mysql_close(con);
return 0;
}

MySQL C API parameterized query fetch result

I've been like 3 hours on this and I can't make this work.
I read MySQL C API documentation like 10 times about mysql_stmt functions.
What I need is like this: mysql_stmt_fetch()
The thing is I need a parametrized query because there is 1 user input.
Code is as follows:
char* regSol(char* token,MYSQL *conn){
char* regnr;
MYSQL_STMT *stmt;
MYSQL_BIND bind[1];
unsigned long str_length;
/*
* Validation
*/
stmt = mysql_stmt_init(conn);
char *sql="SELECT REGNR,Token FROM registed WHERE Token=?";
if(mysql_stmt_prepare(stmt,sql,strlen(sql))){
fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(1);
}
memset(bind, 0, sizeof(bind)); //clears the structure.
bind[0].buffer= 0;
bind[0].buffer_length= 0;
bind[0].length= &str_length;
if(mysql_stmt_bind_result(stmt,bind))
{
fprintf(stderr, " mysql_stmt_bind_result(), failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(1);
}
/*
fetch data
*/
unsigned long long nrow=0;
mysql_stmt_fetch(stmt);
if (str_length > 0)
{
char *data= (char*) malloc(str_length);
bind[0].buffer= data;
bind[0].buffer_length= str_length;
mysql_stmt_fetch_column(stmt, bind, 0, 0);
fprintf(stdout,"DEBUG !! - %s - !!\n",data);
}
return NULL;
}
I already tested mysql_stmt_bind_result and other functions.
The first try was preparing, binding and execute. fetch num of rows and it was always 0. No matter what, always 0.
Can anyone tell me the right way to get a result from a parametrized query?
EDIT 1:
new code that seems what will work but something is weird:
char* regSol(char* token,MYSQL *conn){
/*
* Needs to be completed. I have no idea why I can make this work
* Tested a lot of functions and got some SEGVs and 0 rows.
* And results that aren't even in the database
*/
char* regnr;
MYSQL_STMT *stmt;
MYSQL_BIND bind[1];
unsigned long str_length;
/*
* Validation
*/
stmt = mysql_stmt_init(conn);
char *sql="SELECT REGNR FROM registed WHERE Token=?";
if(mysql_stmt_prepare(stmt,sql,strlen(sql))){
fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(1);
}
memset(bind, 0, sizeof(bind)); //clears the structure.
bind[0].buffer_type=MYSQL_TYPE_STRING;
bind[0].buffer=(char*)token;
bind[0].buffer_length=strlen(token)+1;
bind[0].length= &str_length;
if(mysql_stmt_bind_param(stmt,bind))
{
fprintf(stderr, " mysql_stmt_bind_param(), failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(1);
}
if(mysql_stmt_execute(stmt)){
fprintf(stderr," mysql_stmt_execute(), failed\n");
fprintf(stderr, "%s\n",mysql_stmt_error(stmt));
exit(1);
}
/*
fetch data
*/
//bind result
MYSQL_BIND resbind[1];
unsigned long reslen=0;
resbind[0].buffer=0;
resbind[0].buffer_length=0;
resbind[0].length=&reslen;
if(mysql_stmt_bind_result(stmt,resbind)){
fprintf(stderr," mysql_stmt_bind_result(), failed\n");
fprintf(stderr, "%s\n",mysql_stmt_error(stmt));
exit(1);
}
mysql_stmt_fetch(stmt);
if (reslen > 0) //size of buffer?
{
char *data=(char*)malloc(reslen);
bind[0].buffer=data;
bind[0].buffer_length=reslen;
mysql_stmt_fetch_column(stmt, bind, 0, 0);
fprintf(stdout,"Result Len:%lu\nRegistation NR:%s",reslen,data);
free(data);
}
return "1";
}
The out is:
mysql_stmt_execute(), failed
Got packet bigger than 'max_allowed_packet' bytes
I think it's on here:
if(mysql_stmt_execute(stmt)){
fprintf(stderr," mysql_stmt_execute(), failed\n");
fprintf(stderr, "%s\n",mysql_stmt_error(stmt));
exit(1);
}
So,I created MYSQL_BIND and prepare to bind params (input).
Then I executed. It makes an error which I don't know what It is.
I'm googling how I can access a char* to see the current sql query for troubleshooting.
I think, you have a couple of errors:
1) your query has one (input) parameter and 2 (output) columns, but your defining just one MYSQL_BIND, maybe for input parameter.
2) when you initialize:
bind[0].buffer= 0;
bind[0].buffer_length= 0;
bind[0].length= &str_length;
if this bind is for input parameter, you must change to:
bind[0].buffer= token;
bind[0].buffer_length= strlen(token) + 1;
and pass it with this call:
mysql_stmt_bind_param(stmt,bind);
3) where is your mysql_stmt_execute command? fetch dont work is your query is not executed
I dont check fetch code, but it looks like fine (notice me if not)

efficient way of updating tables using mysql c api

I 'm doing an data logger project where i get data from the sensors and store them in a database . I'm using mysql database which is hosted on Beaglebone (Arm linux based computer ),i'm using C api's to work with the mysql database.
I poll the sensors with a sample time of 5 seconds and get data from them and store them onto the tables as per the below code , the code does what is meant to do i just wanted to know whether there's an efficient way of updating the tables .Below is the code
#include <my_global.h>
#include <mysql.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char *argv[])
{
/* creates a new mysql object */
MYSQL *con = mysql_init(NULL);
float tempval = 0;
float humidval=0;
char query[100]={0};
if (con == NULL)
{
fprintf(stderr, "%s\n", mysql_error(con));
exit(1);
}
/* connect to db */
if(mysql_real_connect(con,"localhost","root","passwrd12#",0,0,0,0)==NULL)
{
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(1);
}
/* Select the db */
if(mysql_select_db(con,"TestDb")!=0)
{
fprintf(stderr,"%s \n",mysql_error(con));
mysql_close(con);
exit(1);
}
while(1)
{
//Read temperature and humidity sensors on pin1 and pin2
tempval=Read_Sensordata(1);
humidval=Read_Sensordata(2)
memset(query,0,sizeof query);
/* update the temperature and humidity values */
sprintf(query,"UPDATE Datavalues SET Temperature = %f,Humidity = %f,Time=NOW() WHERE Rownum=0",tempval,humidval);
if (mysql_query(con,query))
{
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(1);
}
usleep(5000000);
}
mysql_close(con);
exit(0);
}
Rather than execute a fresh query each time, you could prepare the query once and execute it each time with the revised values. For example (without any error checking):
strmov(query, " \
UPDATE Datavalues \
SET Temperature = ?, \
Humidity = ?, \
Time = NOW() \
WHERE Rownum = 0 \
");
MYSQL_STMT *stmt = mysql_stmt_init(con);
mysql_stmt_prepare(stmt, query, strlen(query));
MYSQL_BIND bind[2];
memset(bind, 0, sizeof(bind));
bind[0].buffer_type = bind[1].buffer_type = MYSQL_TYPE_FLOAT;
bind[0].buffer = (char *) &tempval;
bind[1].buffer = (char *) &humidval;
mysql_stmt_bind_param(stmt, bind);
while (1) {
tempval = Read_Sensordata(1);
humidval = Read_Sensordata(2);
mysql_stmt_execute(stmt);
usleep(5000000);
}
mysql_stmt_close(stmt);
Furthermore, you may wish to consider utilising MySQL's Automatic Initialization and Updating for TIMESTAMP and DATETIME to save you having to explicitly set the Time column from within the UPDATE command.

Why does mysql_query() print an error?

I am just starting with C and the MySQL C API. I am using mysql_query() to create a table. According to the manual, the function usage is int mysql_query(MYSQL *mysql, const char *stmt_str), and the function returns 0 if successful or non-zero on error. However, whether I use if (mysql_query()) or if ! (mysql_query()), the program always prints to stdout, "Error 0:". Also, in either case, the program does create the database and table.
#include <my_global.h>
#include <mysql.h>
int main (int argc, char **argv)
{
MYSQL *connection;
const char DATABASE[] = "test";
const char HOSTNAME[] = "localhost";
const char USERNAME[] = "root";
const char PASSWORD[] = "123456";
connection = mysql_init(NULL);
if (connection == NULL)
{
printf("Error %u: %s\n", mysql_errno(connection), mysql_error(connection));
exit(1);
}
if (mysql_real_connect(connection, HOSTNAME, USERNAME, PASSWORD, NULL, 0, NULL, 0) == NULL)
{
printf("Error %u: %s\n", mysql_errno(connection), mysql_error(connection));
exit(1);
}
if (mysql_query(connection, "DROP DATABASE IF EXISTS test"))
{
printf("Error %u: %s\n", mysql_errno(connection), mysql_error(connection));
exit(1);
}
if (mysql_query(connection, "CREATE DATABASE test"))
{
printf("Error %u: %s\n", mysql_errno(connection), mysql_error(connection));
exit(1);
}
if (mysql_select_db(connection, DATABASE))
{
printf("Error %u: %s\n", mysql_errno(connection), mysql_error(connection));
exit(1);
}
/* The problem that I do not understand is happening in the statement below.
* It seems that a successful query returns zero, so I should not see "Error 0:"
*/
if (mysql_query(connection, "CREATE TABLE jobs (id int(11) NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, PRIMARY KEY (id), UNIQUE KEY name_index (name)) ENGINE=InnoDB DEFAULT CHARSET=utf8"));
{
printf("Error %u: %s\n", mysql_errno(connection), mysql_error(connection));
exit(1);
}
mysql_close(connection);
}
You simply have put a semicolon ; at the end of the if statement so the code between the curly braces gets always executed!!!
Take away the ; and everything will work as expected
This is not completely clear from the man page, but my guess would be that the return code of the function is the error code. So you'd have to capture that return value in a variable and then print the value of that variable in case of an error.

mysql_rollback() not working

I had asked this question in another words in my last post and I didn't get the specific answer. So I rephrase. the rollback in the following code is not working. can you please tell me what is wrong:
//Creating and populating a table
C_P_table()
{
MYSQL *conn;
conn = mysql_init(NULL);
if (mysql_real_connect(conn, "localhost", "root",
"password", "testdb", 0, NULL, 0) == NULL) {
printf("Error2 %u: %s\n", mysql_errno(conn), mysql_error(conn));
exit(1);
}
if (mysql_query(conn, "CREATE TABLE writers(name VARCHAR(25))")) {
printf("Error3 %u: %s\n", mysql_errno(conn), mysql_error(conn));
}
mysql_autocommit(conn,0);
if (mysql_query(conn,"START TRANSACTION")) {
printf("Error4 %u: %s\n", mysql_errno(conn), mysql_error(conn));
}
mysql_query(conn,"START TRANSACTION");
mysql_query(conn, "INSERT INTO writers VALUES('Leo Tolstoy')");
mysql_query(conn, "INSERT INTO writers VALUES('Jack London')");
mysql_query(conn, "INSERT INTO writers VALUES('Honore de Balzac')");
mysql_query(conn, "INSERT INTO writers VALUES('Lion Feuchtwanger')");
mysql_query(conn, "INSERT INTO writers VALUES('Emile Zola')");
if(!mysql_rollback(conn))
printf("Roll Back successful\n");
// mysql_query(conn,"ROLLBACK"); //doesn't work neither
mysql_close(conn);
}
int main(int argc, char **argv)
{
C_P_table();
}
My guess is that you are using MyISAM tables, normaly the default table type in MySQL.
So change the line
if (mysql_query(conn, "CREATE TABLE writers(name VARCHAR(25))"))
to
if (mysql_query(conn, "CREATE TABLE writers(name VARCHAR(25)) ENGINE = INNODB"))
and see whats happening.
See: http://dev.mysql.com/doc/refman/5.0/en/storage-engines.html