19 #include <SqlClient.hpp> 
   20 #include <NDBT_Output.hpp> 
   23 SqlClient::SqlClient(
const char* _user,
 
   24                        const char* _password,
 
   25                        const char* _group_suffix):
 
   31   const char* env= getenv(
"MYSQL_HOME");
 
   32   if (env && strlen(env))
 
   34     default_file.assfmt(
"%s/my.cnf", env);
 
   37   if (_group_suffix != NULL){
 
   38     default_group.assfmt(
"client%s", _group_suffix);
 
   41     default_group.assign(
"client.1.atrt");
 
   44   g_info << 
"default_file: " << default_file.c_str() << endl;
 
   45   g_info << 
"default_group: " << default_group.c_str() << endl;
 
   48   password.assign(_password);
 
   52 SqlClient::SqlClient(
MYSQL* mysql):
 
   60 SqlClient::~SqlClient(){
 
   66 SqlClient::isConnected(){
 
   67   if (connected == 
true)
 
   72   return connect() == 0;
 
   82   if ((mysql= mysql_init(NULL)) == NULL){
 
   83     g_err << 
"mysql_init failed" << endl;
 
   88   if (mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, default_file.
c_str()) ||
 
   89       mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, default_group.
c_str()))
 
   91     g_err << 
"mysql_options failed" << endl;
 
  100   if (mysql_real_connect(mysql, NULL, user.
c_str(),
 
  101                          password.
c_str(), 
"atrt", 0, NULL, 0) == NULL)
 
  103     g_err  << 
"Connection to atrt server failed: "<< mysql_error(mysql) << endl;
 
  108   g_err << 
"Connected to MySQL " << mysql_get_server_info(mysql)<< endl;
 
  116 SqlClient::waitConnected(
int timeout) {
 
  118   while(!isConnected()){
 
  121     NdbSleep_MilliSleep(100);
 
  128 SqlClient::disconnect(){
 
  138 static bool is_int_type(enum_field_types 
type){
 
  140   case MYSQL_TYPE_TINY:
 
  141   case MYSQL_TYPE_SHORT:
 
  142   case MYSQL_TYPE_LONGLONG:
 
  143   case MYSQL_TYPE_INT24:
 
  144   case MYSQL_TYPE_LONG:
 
  145   case MYSQL_TYPE_ENUM:
 
  155 SqlClient::runQuery(
const char* sql,
 
  163   g_debug << 
"runQuery: " << endl
 
  164           << 
" sql: '" << sql << 
"'" << endl;
 
  168   if (mysql_stmt_prepare(stmt, sql, strlen(sql)))
 
  170     g_err << 
"Failed to prepare: " << mysql_error(mysql) << endl;
 
  174   uint params= mysql_stmt_param_count(stmt);
 
  176   bzero(bind_param, 
sizeof(bind_param));
 
  178   for(uint 
i= 0; 
i < mysql_stmt_param_count(stmt); 
i++)
 
  185       g_err << 
"param " << 
i << 
" missing" << endl;
 
  191     args.getTypeOf(name.
c_str(), &t);
 
  193     case PropertiesType_Uint32:
 
  194       args.get(name.
c_str(), &val_i);
 
  195       bind_param[
i].buffer_type= MYSQL_TYPE_LONG;
 
  196       bind_param[
i].buffer= (
char*)&val_i;
 
  197       g_debug << 
" param" << name.
c_str() << 
": " << val_i << endl;
 
  199     case PropertiesType_char:
 
  200       args.get(name.
c_str(), &val_s);
 
  201       bind_param[
i].buffer_type= MYSQL_TYPE_STRING;
 
  202       bind_param[
i].buffer= (
char*)val_s;
 
  203       bind_param[
i].buffer_length= strlen(val_s);
 
  204       g_debug << 
" param" << name.
c_str() << 
": " << val_s << endl;
 
  211   if (mysql_stmt_bind_param(stmt, bind_param))
 
  213     g_err << 
"Failed to bind param: " << mysql_error(mysql) << endl;
 
  214     mysql_stmt_close(stmt);
 
  218   if (mysql_stmt_execute(stmt))
 
  220     g_err << 
"Failed to execute: " << mysql_error(mysql) << endl;
 
  221     mysql_stmt_close(stmt);
 
  230   mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (
void*) &one);
 
  232   if (mysql_stmt_store_result(stmt))
 
  234     g_err << 
"Failed to store result: " << mysql_error(mysql) << endl;
 
  235     mysql_stmt_close(stmt);
 
  240   MYSQL_RES* res= mysql_stmt_result_metadata(stmt);
 
  244     uint num_fields= mysql_num_fields(res);
 
  246     bzero(bind_result, 
sizeof(bind_result));
 
  248     for (uint 
i= 0; 
i < num_fields; 
i++)
 
  250       if (is_int_type(fields[
i].type)){
 
  251         bind_result[
i].buffer_type= MYSQL_TYPE_LONG;
 
  252         bind_result[
i].buffer= malloc(
sizeof(
int));
 
  256         uint max_length= fields[
i].max_length + 1;
 
  257         bind_result[
i].buffer_type= MYSQL_TYPE_STRING;
 
  258         bind_result[
i].buffer= malloc(max_length);
 
  259         bind_result[
i].buffer_length= max_length;
 
  263     if (mysql_stmt_bind_result(stmt, bind_result)){
 
  264       g_err << 
"Failed to bind result: " << mysql_error(mysql) << endl;
 
  265       mysql_stmt_close(stmt);
 
  269     while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
 
  272       for (uint 
i= 0; 
i < num_fields; 
i++){
 
  273         if (is_int_type(fields[
i].type))
 
  274           curr.put(fields[
i].name, *(
int*)bind_result[
i].buffer);
 
  276           curr.put(fields[
i].name, (
char*)bind_result[
i].buffer);
 
  278       rows.
put(
"row", row++, &curr);
 
  281     mysql_free_result(res);
 
  283     for (uint 
i= 0; 
i < num_fields; 
i++)
 
  284       free(bind_result[
i].buffer);
 
  289   rows.
put(
"rows", row);
 
  290   rows.
put(
"affected_rows", mysql_affected_rows(mysql));
 
  291   rows.
put(
"mysql_errno", mysql_errno(mysql));
 
  292   rows.
put(
"mysql_error", mysql_error(mysql));
 
  293   rows.
put(
"mysql_sqlstate", mysql_sqlstate(mysql));
 
  294   rows.
put(
"insert_id", mysql_insert_id(mysql));
 
  296   mysql_stmt_close(stmt);
 
  302 SqlClient::doQuery(
const char* 
query){
 
  305   return doQuery(query, args, result);
 
  312   return doQuery(query, args, result);
 
  319   if (!runQuery(query, args, result))
 
  328   return doQuery(str.
c_str());
 
  334   return doQuery(str.
c_str(), result);
 
  341   return doQuery(str.
c_str(), args, result);
 
  348 SqlResultSet::get_row(
int row_num){
 
  349   if(!
get(
"row", row_num, &m_curr_row)){
 
  356 SqlResultSet::next(
void){
 
  357   return get_row(++m_curr_row_num);
 
  361 void SqlResultSet::reset(
void){
 
  367 void SqlResultSet::remove(){
 
  369   row_name.
assfmt(
"row_%d", m_curr_row_num);
 
  370   Properties::remove(row_name.
c_str());
 
  374 SqlResultSet::SqlResultSet(): m_curr_row(0), m_curr_row_num(-1){
 
  377 SqlResultSet::~SqlResultSet(){
 
  380 const char* SqlResultSet::column(
const char* col_name){
 
  383     g_err << 
"ERROR: SqlResultSet::column("<< col_name << 
")" << endl
 
  384           << 
"There is no row loaded, call next() before " 
  385           << 
"acessing the column values" << endl;
 
  388   if (!m_curr_row->get(col_name, &value))
 
  393 uint SqlResultSet::columnAsInt(
const char* col_name){
 
  396     g_err << 
"ERROR: SqlResultSet::columnAsInt("<< col_name << 
")" << endl
 
  397           << 
"There is no row loaded, call next() before " 
  398           << 
"acessing the column values" << endl;
 
  401   if (!m_curr_row->get(col_name, &value))
 
  406 uint SqlResultSet::insertId(){
 
  407   return get_int(
"insert_id");
 
  410 uint SqlResultSet::affectedRows(){
 
  411   return get_int(
"affected_rows");
 
  414 uint SqlResultSet::numRows(
void){
 
  415   return get_int(
"rows");
 
  418 uint SqlResultSet::mysqlErrno(
void){
 
  419   return get_int(
"mysql_errno");
 
  423 const char* SqlResultSet::mysqlError(
void){
 
  424   return get_string(
"mysql_error");
 
  427 const char* SqlResultSet::mysqlSqlstate(
void){
 
  428   return get_string(
"mysql_sqlstate");
 
  431 uint SqlResultSet::get_int(
const char* name){
 
  433   assert(
get(name, &value));
 
  437 const char* SqlResultSet::get_string(
const char* name){
 
  439   assert(
get(name, &value));