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));