我尝试使用带有CLIENT_MULTI_STATEMENT和autocommit=0
连接的MySQL/C,但效果不佳。每次mysql_commit();
时,我都会收到下面的错误消息
错误:mysql_commit()失败,命令不同步;您现在无法运行此命令。
奇怪的是,当我设置autocommit=1;
时,它会很好地工作顺便说一句,我所有的命令都只包含"INSERT",所以我认为不应该出现任何"commands out of sync"错误,因为不会产生"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;
}
有人能帮忙吗?
在处理多个状态时会产生一些"NULL-RSULT",其中只包含"INSERT",因此我们应该在执行mysql_commit()
之前调用一些mysql_next_result()
。
事实上,我们能够在multistatements查询时得到错误消息。所以我用宏观打击成功地解决了我自己的问题。
#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;
}
}
BTW,它还可以在MULTI_STATEMENTS查询时注销错误消息。
TY,所有