#include #include #include #include #include #include #include #include "workflow/Workflow.h" #include "workflow/WFTaskFactory.h" #include "workflow/MySQLResult.h" #include "workflow/WFFacilities.h" using namespace protocol; #define RETRY_MAX 0 volatile bool stop_flag; void mysql_callback(WFMySQLTask *task); void get_next_cmd(WFMySQLTask *task) { int len; char query[4096]; WFMySQLTask *next_task; fprintf(stderr, "mysql> "); while ((fgets(query, 4096, stdin)) && stop_flag == false) { len = strlen(query); if (len > 0 && query[len - 1] == '\n') query[len - 1] = '\0'; if (strncmp(query, "quit", len) == 0 || strncmp(query, "exit", len) == 0) { fprintf(stderr, "Bye\n"); return; } if (len == 0 || strncmp(query, "\0", len) == 0) { fprintf(stderr, "mysql> "); continue; } std::string *url = (std::string *)series_of(task)->get_context(); next_task = WFTaskFactory::create_mysql_task(*url, RETRY_MAX, mysql_callback); next_task->get_req()->set_query(query); series_of(task)->push_back(next_task); break; } return; } void mysql_callback(WFMySQLTask *task) { MySQLResponse *resp = task->get_resp(); MySQLResultCursor cursor(resp); const MySQLField *const *fields; std::vector arr; if (task->get_state() != WFT_STATE_SUCCESS) { fprintf(stderr, "error msg: %s\n", WFGlobal::get_error_string(task->get_state(), task->get_error())); return; } do { if (cursor.get_cursor_status() != MYSQL_STATUS_GET_RESULT && cursor.get_cursor_status() != MYSQL_STATUS_OK) { break; } fprintf(stderr, "---------------- RESULT SET ----------------\n"); if (cursor.get_cursor_status() == MYSQL_STATUS_GET_RESULT) { fprintf(stderr, "cursor_status=%d field_count=%u rows_count=%u\n", cursor.get_cursor_status(), cursor.get_field_count(), cursor.get_rows_count()); //nocopy api fields = cursor.fetch_fields(); for (int i = 0; i < cursor.get_field_count(); i++) { if (i == 0) { fprintf(stderr, "db=%s table=%s\n", fields[i]->get_db().c_str(), fields[i]->get_table().c_str()); fprintf(stderr, " ---------- COLUMNS ----------\n"); } fprintf(stderr, " name[%s] type[%s]\n", fields[i]->get_name().c_str(), datatype2str(fields[i]->get_data_type())); } fprintf(stderr, " _________ COLUMNS END _________\n\n"); while (cursor.fetch_row(arr)) { fprintf(stderr, " ------------ ROW ------------\n"); for (size_t i = 0; i < arr.size(); i++) { fprintf(stderr, " [%s][%s]", fields[i]->get_name().c_str(), datatype2str(arr[i].get_data_type())); if (arr[i].is_string()) { std::string res = arr[i].as_string(); if (res.length() == 0) fprintf(stderr, "[\"\"]\n"); else fprintf(stderr, "[%s]\n", res.c_str()); } else if (arr[i].is_int()) { fprintf(stderr, "[%d]\n", arr[i].as_int()); } else if (arr[i].is_ulonglong()) { fprintf(stderr, "[%llu]\n", arr[i].as_ulonglong()); } else if (arr[i].is_float()) { const void *ptr; size_t len; int data_type; arr[i].get_cell_nocopy(&ptr, &len, &data_type); size_t pos; for (pos = 0; pos < len; pos++) if (*((const char *)ptr + pos) == '.') break; if (pos != len) pos = len - pos - 1; else pos = 0; fprintf(stderr, "[%.*f]\n", (int)pos, arr[i].as_float()); } else if (arr[i].is_double()) { const void *ptr; size_t len; int data_type; arr[i].get_cell_nocopy(&ptr, &len, &data_type); size_t pos; for (pos = 0; pos < len; pos++) if (*((const char *)ptr + pos) == '.') break; if (pos != len) pos = len - pos - 1; else pos= 0; fprintf(stderr, "[%.*lf]\n", (int)pos, arr[i].as_double()); } else if (arr[i].is_date()) { fprintf(stderr, "[%s]\n", arr[i].as_string().c_str()); } else if (arr[i].is_time()) { fprintf(stderr, "[%s]\n", arr[i].as_string().c_str()); } else if (arr[i].is_datetime()) { fprintf(stderr, "[%s]\n", arr[i].as_string().c_str()); } else if (arr[i].is_null()) { fprintf(stderr, "[NULL]\n"); } else { std::string res = arr[i].as_binary_string(); if (res.length() == 0) fprintf(stderr, "[\"\"]\n"); else fprintf(stderr, "[%s]\n", res.c_str()); } } fprintf(stderr, " __________ ROW END __________\n"); } } else if (cursor.get_cursor_status() == MYSQL_STATUS_OK) { fprintf(stderr, " OK. %llu ", cursor.get_affected_rows()); if (cursor.get_affected_rows() == 1) fprintf(stderr, "row "); else fprintf(stderr, "rows "); fprintf(stderr, "affected. %d warnings. insert_id=%llu. %s\n", cursor.get_warnings(), cursor.get_insert_id(), cursor.get_info().c_str()); } fprintf(stderr, "________________ RESULT SET END ________________\n\n"); } while (cursor.next_result_set()); if (resp->get_packet_type() == MYSQL_PACKET_ERROR) { fprintf(stderr, "ERROR. error_code=%d %s\n", task->get_resp()->get_error_code(), task->get_resp()->get_error_msg().c_str()); } else if (resp->get_packet_type() == MYSQL_PACKET_OK) // just check origin APIs { fprintf(stderr, "OK. %llu ", task->get_resp()->get_affected_rows()); if (task->get_resp()->get_affected_rows() == 1) fprintf(stderr, "row "); else fprintf(stderr, "rows "); fprintf(stderr, "affected. %d warnings. insert_id=%llu. %s\n", task->get_resp()->get_warnings(), task->get_resp()->get_last_insert_id(), task->get_resp()->get_info().c_str()); } get_next_cmd(task); return; } static void sighandler(int signo) { stop_flag = true; } int main(int argc, char *argv[]) { WFMySQLTask *task; if (argc != 2) { fprintf(stderr, "USAGE: %s \n" " url format: mysql://root:password@host:port/dbname?character_set=charset\n" " example: mysql://root@test.mysql.com/test\n", argv[0]); return 0; } signal(SIGINT, sighandler); signal(SIGTERM, sighandler); std::string url = argv[1]; if (strncasecmp(argv[1], "mysql://", 8) != 0 && strncasecmp(argv[1], "mysqls://", 9) != 0) { url = "mysql://" + url; } const char *query = "show databases"; stop_flag = false; task = WFTaskFactory::create_mysql_task(url, RETRY_MAX, mysql_callback); task->get_req()->set_query(query); WFFacilities::WaitGroup wait_group(1); SeriesWork *series = Workflow::create_series_work(task, [&wait_group](const SeriesWork *series) { wait_group.done(); }); series->set_context(&url); series->start(); wait_group.wait(); return 0; }