2014-10-10 75 views
0

我尝试使用CLIENT_MULTI_STATEMENTS和autocommit=0 connect连接MySQL/C,但这些工作并不好。我收到的每一次下面的错误信息而mysql_commit();MySQL/C提交失败,多语句

Error: mysql_commit() failed with Commands out of sync; you can't run this command now.

奇怪的是,它会工作得很好,当我设置autocommit=1; 顺便说一句,我的所有命令只包含“插入”,所以我觉得不应该有任何“命令不同步“的错误没有'RESULT'会产生。

你所有可能永远都不想这样写下面的任何代码,笑

我的宏:

#ifndef MACRO_H_ 
#define MACRO_H_ 

#define DBOPEN(x) x=mysql_init(NULL);\ 
    if(x==NULL){\ 
     DBErrLog("Error: mysql_init() failed.");return 1;\ 
    }\ 
    if(mysql_options(x, MYSQL_SET_CHARSET_NAME, "ascii")){\ 
     DBErrLog("Warning: mysql_option() SET mysql_set_charset_name TO ascii failed.");\ 
    }\ 
    if(mysql_options(x, MYSQL_INIT_COMMAND, "SET autocommit=0")){\ 
     DBErrLog("Warning: mysql_option() SET autocommit=0 failed.");\ 
    }\ 
    if(!mysql_real_connect(x, C_DBHOST, C_DBUSR, C_DBPWD, C_DATABASE, 0, NULL, CLIENT_MULTI_STATEMENTS)){\ 
     DBErrLog("Error: connect to database failed with %s.", mysql_error(x));\ 
     return 1;\ 
    } 

#define DBQUERY(x, y) if(mysql_query(x, y)){\ 
     DBErrLog("Error: mysql_query(%s) failed with %s.", y, mysql_error(x));\ 
     return 1;\ 
    } 

#define DBREALQUERY(x, y, z) if(mysql_real_query(x, y, z)){\ 
     DBErrLog("Error: mysql_real_query(%s) failed with %s.", y, mysql_error(x));\ 
     return 1;\ 
    } 

#define DBCOMMIT(x) if(mysql_commit(x)){\ 
     DBErrLog("Error: mysql_commit() failed with %s.", mysql_error(x));\ 
     return 1;\ 
    } 

#define RESCATCH(x, y) y=mysql_store_result(x);\ 
    if(y==NULL){\ 
     DBErrLog("Error: mysql_store_result() failed with %s.", mysql_error(x));\ 
     return 1;\ 
    } 

#define DBCLOSE(x) mysql_close(x) 

#define RESFREE(x) mysql_free_result(x) 

#define ROWCATCH(x, y) (x=(MYSQL_ROW*)mysql_fetch_row(y)) 

#define SAPPEND(to, msg) {\ 
     const char *str=msg;\ 
     while(*str)*to++=*str++;\ 
    } 

#define IAPPEND(to, key) {\ 
     char buf[16];\ 
     sprintf(buf, "0x%x", key);\ 
     SAPPEND(to, buf);\ 
    } 

#define STOIP(to, key) {\ 
     sscanf((char*)key, "%d", to);\ 
    } 

#define ESAPPEND(sql, to, from, size) to+=mysql_real_escape_string(sql, to, from, size) 

#define SERIALIZE(to, from, size) {\ 
     char *p=(char*)from;\ 
     size_t i;for(i=0;i<size;i++)\ 
      *to++=*p++;\ 
    } 

#define SERIAPPEND(sql, to, from, size) {\ 
     char bufh[256], *buft;\ 
     buft=bufh;\ 
     SERIALIZE(buft, from, size);\ 
     ESAPPEND(sql, to, bufh, size);\ 
    } 

#define UNSERIALIZE(to, from, size) {\ 
     char *dst=(char*)to;\ 
     char *src=(char*)from;\ 
     size_t i;for(i=0;i<size;i++)\ 
      *dst++=*src++;\ 
    } 

#endif /* MACRO_H_ */ 

我的错误代码:

int CamInsert(void *vHead, void *vTail, void *vK){ 
    if(vTail<=vHead)return 2; 
    char bufHead[C_BUFSIZE], *bufTail; 
    MYSQL *sql; 
    DBOPEN(sql); 
    bufTail=bufHead; 
    p2_t *head=(p2_t*)vHead; 
    p2_t *tail=(p2_t*)vTail; 
    p2_t *p2; 
    SAPPEND(bufTail, "INSERT INTO p2(idxSelf, idxCam, idx3d, pos, ent) VALUES"); 
    for(p2=head; p2!=tail; p2++){ 
     if(p2!=head)SAPPEND(bufTail, ", "); 
     SAPPEND(bufTail, "("); 
     IAPPEND(bufTail, p2->idxSelf); 
     SAPPEND(bufTail, ", "); 
     IAPPEND(bufTail, p2->idxCam); 
     SAPPEND(bufTail, ", "); 
     IAPPEND(bufTail, p2->idx3d); 
     SAPPEND(bufTail, ", '"); 
     SERIAPPEND(sql, bufTail, p2->pos, sizeof(float)*2); 
     SAPPEND(bufTail, "', '"); 
     SERIAPPEND(sql, bufTail, p2->ent, sizeof(unsigned char)*C_DIMSIZE); 
     SAPPEND(bufTail, "')"); 
    } 
    cam_t *cam=(cam_t*)malloc(sizeof(cam_t)); 
    cam->idxSelf=head->idxCam; 
    cam->idxGroup=cam->idxSelf; 
    cam->adjusted=0; 
    int *K=(int*)vK, i, j; 
    for(i=0;i<3;i++) 
     for(j=0;j<3;j++) 
      cam->K[i][j]=K[i*3+j]; 
    for(i=0;i<3;i++) 
     for(j=0;j<4;j++) 
      cam->P[i][j]=(i==j)?1.0f:0.0f; 
    SAPPEND(bufTail, "; INSERT INTO cam(idxSelf, idxGroup, adjusted, K, P) VALUES("); 
    IAPPEND(bufTail, cam->idxSelf); 
    SAPPEND(bufTail, ", "); 
    IAPPEND(bufTail, cam->idxGroup); 
    SAPPEND(bufTail, ", "); 
    IAPPEND(bufTail, cam->adjusted); 
    SAPPEND(bufTail, ", '"); 
    SERIAPPEND(sql, bufTail, cam->K, sizeof(double)*3*3); 
    SAPPEND(bufTail, "', '"); 
    SERIAPPEND(sql, bufTail, cam->P, sizeof(double)*3*4); 
    SAPPEND(bufTail, "')"); 
    free(cam); 
    DBREALQUERY(sql, bufHead, bufTail-bufHead); 
    DBCOMMIT(sql); 
    DBCLOSE(sql); 
    return 0; 
} 

任何人都可以帮助吗?

+0

为什么要创建一个有错误的宏'SAPPEND'(whcih不空终止结果)时,有一个工作的库函数'strcat'?你也应该把你的宏转换成函数。 – 2014-10-10 10:47:48

+0

另外,在你的SQL语句中使用参数会使你的代码更安全:http://xkcd.com/327/ – 2014-10-10 10:50:10

+0

@KlasLindbäck,我认为使用宏SAPPEND是安全的,因为我只是使用mysql_real_query(),它使用查询长度参数。而strcat可能对维护空终止而不是终止指针具有较低的效率。 THX,都一样。 – 2014-10-11 01:32:51

回答

0

在使用MULTI_STATEMENTS时只会产生一些'NULL-RESULT'而只包含'INSERT',因此在执行mysql_commit()之前我们应该调用一些mysql_next_result()

事实上,我们可以在多个状态查询时获取错误消息。所以我用宏伟的吹捧来成功地解决我自己的问题。

#define DBMRFREE(x) {\ 
     while(1){\ 
      MYSQL_RES *r=mysql_store_result(x);\ 
      if(r!=NULL)mysql_free_result(r);\ 
      int msg=mysql_next_result(x);\ 
      if(msg>0){\ 
       DBErrLog("Error: mysql_next_result() failed whit %s.", mysql_error(x));\ 
      }else if(msg<0)break;\ 
     }\ 
    } 

顺便说一句,其中也可以注销错误消息,同时多个状态查询。

TY,ALL