00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <mysql/mysql.h>
00039 #include <mysql/errmsg.h>
00040 #include <mysql/mysql_version.h>
00041 #include "../../mem/mem.h"
00042 #include "../../dprint.h"
00043 #include "../../db/db_query.h"
00044 #include "../../db/db_ut.h"
00045 #include "val.h"
00046 #include "my_con.h"
00047 #include "res.h"
00048 #include "row.h"
00049 #include "db_mysql.h"
00050 #include "dbase.h"
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 static int db_mysql_submit_query(const db_con_t* _h, const str* _s)
00069 {
00070 time_t t;
00071 int i, code;
00072
00073 if (!_h || !_s || !_s->s) {
00074 LM_ERR("invalid parameter value\n");
00075 return -1;
00076 }
00077
00078 if (db_mysql_ping_interval) {
00079 t = time(0);
00080 if ((t - CON_TIMESTAMP(_h)) > db_mysql_ping_interval) {
00081 if (mysql_ping(CON_CONNECTION(_h))) {
00082 LM_WARN("driver error on ping: %s\n", mysql_error(CON_CONNECTION(_h)));
00083 }
00084 }
00085
00086
00087
00088
00089
00090 CON_TIMESTAMP(_h) = t;
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 for (i=0; i < (db_mysql_auto_reconnect ? 3 : 1); i++) {
00108 if (mysql_real_query(CON_CONNECTION(_h), _s->s, _s->len) == 0) {
00109 return 0;
00110 }
00111 code = mysql_errno(CON_CONNECTION(_h));
00112 if (code != CR_SERVER_GONE_ERROR && code != CR_SERVER_LOST) {
00113 break;
00114 }
00115 }
00116 LM_ERR("driver error on query: %s\n", mysql_error(CON_CONNECTION(_h)));
00117 return -2;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 db_con_t* db_mysql_init(const str* _url)
00129 {
00130 return db_do_init(_url, (void *)db_mysql_new_connection);
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140 void db_mysql_close(db_con_t* _h)
00141 {
00142 db_do_close(_h, db_mysql_free_connection);
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152 static int db_mysql_store_result(const db_con_t* _h, db_res_t** _r)
00153 {
00154 if ((!_h) || (!_r)) {
00155 LM_ERR("invalid parameter value\n");
00156 return -1;
00157 }
00158
00159 *_r = db_new_result();
00160 if (*_r == 0) {
00161 LM_ERR("no memory left\n");
00162 return -2;
00163 }
00164
00165 CON_RESULT(_h) = mysql_store_result(CON_CONNECTION(_h));
00166 if (!CON_RESULT(_h)) {
00167 if (mysql_field_count(CON_CONNECTION(_h)) == 0) {
00168 (*_r)->col.n = 0;
00169 (*_r)->n = 0;
00170 goto done;
00171 } else {
00172 LM_ERR("driver error: %s\n", mysql_error(CON_CONNECTION(_h)));
00173 db_free_result(*_r);
00174 *_r = 0;
00175 return -3;
00176 }
00177 }
00178
00179 if (db_mysql_convert_result(_h, *_r) < 0) {
00180 LM_ERR("error while converting result\n");
00181 LM_DBG("freeing result set at %p\n", _r);
00182 pkg_free(*_r);
00183 *_r = 0;
00184
00185
00186
00187 mysql_free_result(CON_RESULT(_h));
00188 #if (MYSQL_VERSION_ID >= 40100)
00189 while( mysql_next_result( CON_CONNECTION(_h) ) > 0 ) {
00190 MYSQL_RES *res = mysql_store_result( CON_CONNECTION(_h) );
00191 mysql_free_result(res);
00192 }
00193 #endif
00194 CON_RESULT(_h) = 0;
00195 return -4;
00196 }
00197
00198 done:
00199 #if (MYSQL_VERSION_ID >= 40100)
00200 while( mysql_next_result( CON_CONNECTION(_h) ) > 0 ) {
00201 MYSQL_RES *res = mysql_store_result( CON_CONNECTION(_h) );
00202 mysql_free_result(res);
00203 }
00204 #endif
00205
00206 return 0;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216 int db_mysql_free_result(db_con_t* _h, db_res_t* _r)
00217 {
00218 if ((!_h) || (!_r)) {
00219 LM_ERR("invalid parameter value\n");
00220 return -1;
00221 }
00222
00223 if (db_free_result(_r) < 0) {
00224 LM_ERR("unable to free result structure\n");
00225 return -1;
00226 }
00227 mysql_free_result(CON_RESULT(_h));
00228 CON_RESULT(_h) = 0;
00229 return 0;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 int db_mysql_query(const db_con_t* _h, const db_key_t* _k, const db_op_t* _op,
00247 const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
00248 const db_key_t _o, db_res_t** _r)
00249 {
00250 return db_do_query(_h, _k, _op, _v, _c, _n, _nc, _o, _r,
00251 db_mysql_val2str, db_mysql_submit_query, db_mysql_store_result);
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 int db_mysql_fetch_result(const db_con_t* _h, db_res_t** _r, const int nrows)
00270 {
00271 int rows, i;
00272
00273 if (!_h || !_r || nrows < 0) {
00274 LM_ERR("Invalid parameter value\n");
00275 return -1;
00276 }
00277
00278
00279 if (nrows == 0) {
00280 db_free_result(*_r);
00281 *_r = 0;
00282 return 0;
00283 }
00284
00285 if(*_r==0) {
00286
00287 *_r = db_new_result();
00288 if (*_r == 0) {
00289 LM_ERR("no memory left\n");
00290 return -2;
00291 }
00292
00293 CON_RESULT(_h) = mysql_store_result(CON_CONNECTION(_h));
00294 if (!CON_RESULT(_h)) {
00295 if (mysql_field_count(CON_CONNECTION(_h)) == 0) {
00296 (*_r)->col.n = 0;
00297 (*_r)->n = 0;
00298 return 0;
00299 } else {
00300 LM_ERR("driver error: %s\n", mysql_error(CON_CONNECTION(_h)));
00301 db_free_result(*_r);
00302 *_r = 0;
00303 return -3;
00304 }
00305 }
00306 if (db_mysql_get_columns(_h, *_r) < 0) {
00307 LM_ERR("error while getting column names\n");
00308 return -4;
00309 }
00310
00311 RES_NUM_ROWS(*_r) = mysql_num_rows(CON_RESULT(_h));
00312 if (!RES_NUM_ROWS(*_r)) {
00313 LM_DBG("no rows returned from the query\n");
00314 RES_ROWS(*_r) = 0;
00315 return 0;
00316 }
00317
00318 } else {
00319
00320 if(RES_ROWS(*_r)!=0)
00321 db_free_rows(*_r);
00322 RES_ROWS(*_r) = 0;
00323 RES_ROW_N(*_r) = 0;
00324 }
00325
00326
00327 rows = RES_NUM_ROWS(*_r) - RES_LAST_ROW(*_r);
00328
00329
00330 if(rows<=0)
00331 return 0;
00332
00333
00334
00335 if(nrows < rows)
00336 rows = nrows;
00337
00338 RES_ROW_N(*_r) = rows;
00339
00340 LM_DBG("converting row %d of %d count %d\n", RES_LAST_ROW(*_r),
00341 RES_NUM_ROWS(*_r), RES_ROW_N(*_r));
00342
00343 RES_ROWS(*_r) = (struct db_row*)pkg_malloc(sizeof(db_row_t) * rows);
00344 if (!RES_ROWS(*_r)) {
00345 LM_ERR("no memory left\n");
00346 return -5;
00347 }
00348
00349 for(i = 0; i < rows; i++) {
00350 CON_ROW(_h) = mysql_fetch_row(CON_RESULT(_h));
00351 if (!CON_ROW(_h)) {
00352 LM_ERR("driver error: %s\n", mysql_error(CON_CONNECTION(_h)));
00353 RES_ROW_N(*_r) = i;
00354 db_free_rows(*_r);
00355 return -6;
00356 }
00357 if (db_mysql_convert_row(_h, *_r, &(RES_ROWS(*_r)[i])) < 0) {
00358 LM_ERR("error while converting row #%d\n", i);
00359 RES_ROW_N(*_r) = i;
00360 db_free_rows(*_r);
00361 return -7;
00362 }
00363 }
00364
00365
00366 RES_LAST_ROW(*_r) += rows;
00367 return 0;
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377 int db_mysql_raw_query(const db_con_t* _h, const str* _s, db_res_t** _r)
00378 {
00379 return db_do_raw_query(_h, _s, _r, db_mysql_submit_query,
00380 db_mysql_store_result);
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 int db_mysql_insert(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v, const int _n)
00393 {
00394 return db_do_insert(_h, _k, _v, _n, db_mysql_val2str,
00395 db_mysql_submit_query);
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 int db_mysql_delete(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
00409 const db_val_t* _v, const int _n)
00410 {
00411 return db_do_delete(_h, _k, _o, _v, _n, db_mysql_val2str,
00412 db_mysql_submit_query);
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 int db_mysql_update(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
00429 const db_val_t* _v, const db_key_t* _uk, const db_val_t* _uv, const int _n,
00430 const int _un)
00431 {
00432 return db_do_update(_h, _k, _o, _v, _uk, _uv, _n, _un, db_mysql_val2str,
00433 db_mysql_submit_query);
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 int db_mysql_replace(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v, const int _n)
00446 {
00447 return db_do_replace(_h, _k, _v, _n, db_mysql_val2str,
00448 db_mysql_submit_query);
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458 int db_last_inserted_id(const db_con_t* _h)
00459 {
00460 if (!_h) {
00461 LM_ERR("invalid parameter value\n");
00462 return -1;
00463 }
00464 return mysql_insert_id(CON_CONNECTION(_h));
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 int db_insert_update(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v,
00476 const int _n)
00477 {
00478 int off, ret;
00479 static str sql_str;
00480 static char sql_buf[SQL_BUF_LEN];
00481
00482 if ((!_h) || (!_k) || (!_v) || (!_n)) {
00483 LM_ERR("invalid parameter value\n");
00484 return -1;
00485 }
00486
00487 ret = snprintf(sql_buf, SQL_BUF_LEN, "insert into %.*s (", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00488 if (ret < 0 || ret >= SQL_BUF_LEN) goto error;
00489 off = ret;
00490
00491 ret = db_print_columns(sql_buf + off, SQL_BUF_LEN - off, _k, _n);
00492 if (ret < 0) return -1;
00493 off += ret;
00494
00495 ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, ") values (");
00496 if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
00497 off += ret;
00498 ret = db_print_values(_h, sql_buf + off, SQL_BUF_LEN - off, _v, _n, db_mysql_val2str);
00499 if (ret < 0) return -1;
00500 off += ret;
00501
00502 *(sql_buf + off++) = ')';
00503
00504 ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, " on duplicate key update ");
00505 if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
00506 off += ret;
00507
00508 ret = db_print_set(_h, sql_buf + off, SQL_BUF_LEN - off, _k, _v, _n, db_mysql_val2str);
00509 if (ret < 0) return -1;
00510 off += ret;
00511
00512 sql_str.s = sql_buf;
00513 sql_str.len = off;
00514
00515 if (db_mysql_submit_query(_h, &sql_str) < 0) {
00516 LM_ERR("error while submitting query\n");
00517 return -2;
00518 }
00519 return 0;
00520
00521 error:
00522 LM_ERR("error while preparing insert_update operation\n");
00523 return -1;
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533 int db_mysql_use_table(db_con_t* _h, const str* _t)
00534 {
00535 return db_use_table(_h, _t);
00536 }