#include #include #include #include #include #include MYSQL *db_connect(const char *dbname); void db_disconnect(MYSQL *db); void db_do_query(MYSQL *db, const char *query); static void die(MYSQL *db, char *fmt, ...); const char *server_groups[] = { "test_libmysqld_SERVER", "embedded", "server", NULL }; // //////////////////////////////////////////////////////////////////////////// // Error Helper Function // //////////////////////////////////////////////////////////////////////////// int Error( MYSQL* _mysql ) { int errorCode = (int)mysql_errno(_mysql); const char *mySQLMessage = mysql_error(_mysql); printf("\n%d - %s\n", errorCode, mySQLMessage); return (int)errorCode; } /******************************************************** * process the stmt result set * *********************************************************/ #define MAX_RES_FIELDS 50 #define MAX_FIELD_DATA_SIZE 255 uint my_process_stmt_result(MYSQL_STMT *stmt) { int field_count; uint row_count= 0; MYSQL_BIND buffer[MAX_RES_FIELDS]; MYSQL_FIELD *field; MYSQL_RES *result; char data[MAX_RES_FIELDS][MAX_FIELD_DATA_SIZE]; ulong length[MAX_RES_FIELDS]; my_bool is_null[MAX_RES_FIELDS]; int rc, i; if (!(result= mysql_get_metadata(stmt))) /* No meta info */ { while (!mysql_fetch(stmt)) row_count++; return row_count; } field_count= mysql_num_fields(result); for(i=0; i < field_count; i++) { buffer[i].buffer_type= MYSQL_TYPE_STRING; buffer[i].buffer_length= MAX_FIELD_DATA_SIZE; buffer[i].length= &length[i]; buffer[i].buffer= (char*) data[i]; buffer[i].is_null= &is_null[i]; } rc= mysql_bind_result(stmt,buffer); rc= mysql_stmt_store_result(stmt); mysql_field_seek(result, 0); while (mysql_fetch(stmt) == 0) { fputc('\t',stdout); fputc('|',stdout); mysql_field_seek(result,0); for (i=0; i < field_count; i++) { field = mysql_fetch_field(result); if (is_null[i]) fprintf(stdout, " %-*s |", (int) field->max_length, "NULL"); else if (length[i] == 0) { data[i][0]='\0'; /* unmodified buffer */ fprintf(stdout, " %*s |", (int) field->max_length, data[i]); } else if (IS_NUM(field->type)) fprintf(stdout, " %*s |", (int) field->max_length, data[i]); else fprintf(stdout, " %-*s |", (int) field->max_length, data[i]); } fputc('\t',stdout); fputc('\n',stdout); row_count++; } fprintf(stdout,"\n\t%d %s returned\n", row_count, row_count == 1 ? "row" : "rows"); mysql_free_result(result); return row_count; } static void test_subselect(MYSQL *mysql) { MYSQL_STMT *stmt; MYSQL_BIND bind[3]; char buffer[3][10]; int rc, i; char query[1000]; unsigned long lengths[3]; strcpy(query, "SELECT SQL_BUFFER_RESULT " "(SELECT COUNT(DISTINCT b) FROM t1 GROUP BY t1.a LIMIT 1) " "FROM t1,t2 WHERE t1.a=t2.b"); db_do_query(mysql, query); /* remove this line to get the bug with locks */ stmt = mysql_prepare(mysql, query, strlen(query)); for (i=0; i<10; i++) { rc= mysql_execute(stmt); my_process_stmt_result(stmt); } mysql_stmt_close(stmt); } int main(int argc, char **argv) { MYSQL *mysql; mysql_server_init(argc, argv, (char **)server_groups); mysql= db_connect("test"); test_subselect(mysql); mysql_server_end(); return 0; } static void die(MYSQL *db, char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); (void)putc('\n', stderr); if (db) db_disconnect(db); exit(EXIT_FAILURE); } MYSQL * db_connect(const char *dbname) { MYSQL *db = mysql_init(NULL); if (!db) die(db, "mysql_init failed: no memory"); /* * Notice that the client and server use separate group names. * This is critical, because the server will not accept the * client's options, and vice versa. */ mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test_libmysqld_CLIENT"); if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0)) die(db, "mysql_real_connect failed: %s", mysql_error(db)); return db; } void db_disconnect(MYSQL *db) { mysql_close(db); } void db_do_query(MYSQL *db, const char *query) { if (mysql_query(db, query) != 0) goto err; if (mysql_field_count(db) > 0) { MYSQL_RES *res; MYSQL_ROW row, end_row; int num_fields; if (!(res = mysql_store_result(db))) goto err; num_fields = mysql_num_fields(res); while ((row = mysql_fetch_row(res))) { (void)fputs(">> ", stdout); for (end_row = row + num_fields; row < end_row; ++row) (void)printf("%s\t", *row ? (char*)*row : "NULL"); (void)fputc('\n', stdout); } (void)fputc('\n', stdout); mysql_free_result(res); } else (void)printf("Affected rows: %lld\n", mysql_affected_rows(db)); return; err: die(db, "db_do_query failed: %s [%s]", mysql_error(db), query); }