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
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define MAXCOLUMNS 512
00069
00070 #include <string.h>
00071 #include <stdio.h>
00072 #include "../../dprint.h"
00073 #include "../../mem/mem.h"
00074 #include "../../db/db.h"
00075 #include "../../db/db_ut.h"
00076 #include "../../db/db_query.h"
00077 #include "dbase.h"
00078 #include "pg_con.h"
00079 #include "val.h"
00080 #include "res.h"
00081
00082 static void db_postgres_free_query(const db_con_t* _con);
00083
00084
00085
00086
00087
00088
00089
00090
00091 db_con_t *db_postgres_init(const str* _url)
00092 {
00093 return db_do_init(_url, (void*) db_postgres_new_connection);
00094 }
00095
00096
00097
00098
00099
00100
00101
00102 void db_postgres_close(db_con_t* _h)
00103 {
00104 db_do_close(_h, db_postgres_free_connection);
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114 static int db_postgres_submit_query(const db_con_t* _con, const str* _s)
00115 {
00116 if(! _con || !_s || !_s->s)
00117 {
00118 LM_ERR("invalid parameter value\n");
00119 return(-1);
00120 }
00121
00122
00123 switch(PQstatus(CON_CONNECTION(_con)))
00124 {
00125 case CONNECTION_OK:
00126 break;
00127 case CONNECTION_BAD:
00128 LM_DBG("connection reset\n");
00129 PQreset(CON_CONNECTION(_con));
00130 break;
00131 case CONNECTION_STARTED:
00132 case CONNECTION_MADE:
00133 case CONNECTION_AWAITING_RESPONSE:
00134 case CONNECTION_AUTH_OK:
00135 case CONNECTION_SETENV:
00136 case CONNECTION_SSL_STARTUP:
00137 case CONNECTION_NEEDED:
00138 default:
00139 LM_ERR("%p PQstatus(%s) invalid: %.*s\n", _con,
00140 PQerrorMessage(CON_CONNECTION(_con)), _s->len, _s->s);
00141 return -1;
00142 }
00143
00144
00145 db_postgres_free_query(_con);
00146
00147
00148 if (PQsendQuery(CON_CONNECTION(_con), _s->s)) {
00149 LM_DBG("%p PQsendQuery(%.*s)\n", _con, _s->len, _s->s);
00150 } else {
00151 LM_ERR("%p PQsendQuery Error: %s Query: %.*s\n", _con,
00152 PQerrorMessage(CON_CONNECTION(_con)), _s->len, _s->s);
00153 return -1;
00154 }
00155
00156 return 0;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 int db_postgres_fetch_result(const db_con_t* _con, db_res_t** _res, const int nrows)
00176 {
00177 int rows;
00178 PGresult *res = NULL;
00179 ExecStatusType pqresult;
00180
00181 if (!_con || !_res || nrows < 0) {
00182 LM_ERR("invalid parameter value\n");
00183 return -1;
00184 }
00185
00186
00187 if (nrows == 0) {
00188 if (*_res)
00189 db_free_result(*_res);
00190
00191 *_res = 0;
00192 return 0;
00193 }
00194
00195 if (*_res == NULL) {
00196
00197 *_res = db_new_result();
00198
00199
00200 while (1) {
00201 if ((res = PQgetResult(CON_CONNECTION(_con)))) {
00202 CON_RESULT(_con) = res;
00203 } else {
00204 break;
00205 }
00206 }
00207 pqresult = PQresultStatus(CON_RESULT(_con));
00208 LM_DBG("%p PQresultStatus(%s) PQgetResult(%p)\n", _con,
00209 PQresStatus(pqresult), CON_RESULT(_con));
00210
00211 switch(pqresult) {
00212 case PGRES_COMMAND_OK:
00213
00214 return 0;
00215
00216 case PGRES_TUPLES_OK:
00217
00218 if (db_postgres_get_columns(_con, *_res) < 0) {
00219 LM_ERR("failed to get column names\n");
00220 return -2;
00221 }
00222 break;
00223
00224 case PGRES_FATAL_ERROR:
00225 LM_ERR("%p - invalid query, execution aborted\n", _con);
00226 LM_ERR("%p - PQresultStatus(%s)\n", _con, PQresStatus(pqresult));
00227 LM_ERR("%p: %s\n", _con, PQresultErrorMessage(CON_RESULT(_con)));
00228 if (*_res)
00229 db_free_result(*_res);
00230 *_res = 0;
00231 return -3;
00232
00233 case PGRES_EMPTY_QUERY:
00234
00235 case PGRES_NONFATAL_ERROR:
00236
00237 case PGRES_COPY_OUT:
00238 case PGRES_COPY_IN:
00239
00240 case PGRES_BAD_RESPONSE:
00241 default:
00242 LM_ERR("%p - probable invalid query\n", _con);
00243 LM_ERR("%p - PQresultStatus(%s)\n", _con, PQresStatus(pqresult));
00244 LM_ERR("%p: %s\n", _con, PQresultErrorMessage(CON_RESULT(_con)));
00245 if (*_res)
00246 db_free_result(*_res);
00247 *_res = 0;
00248 return -4;
00249 }
00250
00251 } else {
00252 if(RES_ROWS(*_res) != NULL) {
00253 db_free_rows(*_res);
00254 }
00255 RES_ROWS(*_res) = 0;
00256 RES_ROW_N(*_res) = 0;
00257 }
00258
00259
00260 RES_NUM_ROWS(*_res) = PQntuples(CON_RESULT(_con));
00261
00262
00263 rows = RES_NUM_ROWS(*_res) - RES_LAST_ROW(*_res);
00264
00265
00266 if (rows <= 0)
00267 return 0;
00268
00269
00270
00271 if (nrows < rows)
00272 rows = nrows;
00273
00274 RES_ROW_N(*_res) = rows;
00275
00276 LM_DBG("converting row %d of %d count %d\n", RES_LAST_ROW(*_res),
00277 RES_NUM_ROWS(*_res), RES_ROW_N(*_res));
00278
00279 if (db_postgres_convert_rows(_con, *_res) < 0) {
00280 LM_ERR("failed to convert rows\n");
00281 if (*_res)
00282 db_free_result(*_res);
00283
00284 *_res = 0;
00285 return -3;
00286 }
00287
00288
00289 RES_LAST_ROW(*_res) += rows;
00290 return 0;
00291 }
00292
00293
00294
00295
00296
00297
00298 static void db_postgres_free_query(const db_con_t* _con)
00299 {
00300 if(CON_RESULT(_con))
00301 {
00302 LM_DBG("PQclear(%p) result set\n", CON_RESULT(_con));
00303 PQclear(CON_RESULT(_con));
00304 CON_RESULT(_con) = 0;
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315 int db_postgres_free_result(db_con_t* _con, db_res_t* _r)
00316 {
00317 if ((!_con) || (!_r)) {
00318 LM_ERR("invalid parameter value\n");
00319 return -1;
00320 }
00321 if (db_free_result(_r) < 0) {
00322 LM_ERR("unable to free result structure\n");
00323 return -1;
00324 }
00325 db_postgres_free_query(_con);
00326 return 0;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 int db_postgres_query(const db_con_t* _h, const db_key_t* _k, const db_op_t* _op,
00344 const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
00345 const db_key_t _o, db_res_t** _r)
00346 {
00347 return db_do_query(_h, _k, _op, _v, _c, _n, _nc, _o, _r, db_postgres_val2str,
00348 db_postgres_submit_query, db_postgres_store_result);
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 int db_postgres_raw_query(const db_con_t* _h, const str* _s, db_res_t** _r)
00360 {
00361 return db_do_raw_query(_h, _s, _r, db_postgres_submit_query,
00362 db_postgres_store_result);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 int db_postgres_store_result(const db_con_t* _con, db_res_t** _r)
00380 {
00381 PGresult *res = NULL;
00382 ExecStatusType pqresult;
00383 int rc = 0;
00384
00385 *_r = db_new_result();
00386 if (*_r==NULL) {
00387 LM_ERR("failed to init new result\n");
00388 rc = -1;
00389 goto done;
00390 }
00391
00392 while (1) {
00393 if ((res = PQgetResult(CON_CONNECTION(_con)))) {
00394 CON_RESULT(_con) = res;
00395 } else {
00396 break;
00397 }
00398 }
00399
00400 pqresult = PQresultStatus(CON_RESULT(_con));
00401
00402 LM_DBG("%p PQresultStatus(%s) PQgetResult(%p)\n", _con,
00403 PQresStatus(pqresult), CON_RESULT(_con));
00404
00405 switch(pqresult) {
00406 case PGRES_COMMAND_OK:
00407
00408
00409 rc = 0;
00410 break;
00411
00412 case PGRES_TUPLES_OK:
00413
00414
00415 if (db_postgres_convert_result(_con, *_r) < 0) {
00416 LM_ERR("error while converting result\n");
00417 LM_DBG("freeing result set at %p\n", _r);
00418 pkg_free(*_r);
00419 *_r = 0;
00420 rc = -4;
00421 break;
00422 }
00423 rc = 0;
00424 break;
00425
00426 case PGRES_FATAL_ERROR:
00427 LM_ERR("invalid query, execution aborted\n");
00428 LM_ERR("driver error: %s, %s\n", PQresStatus(pqresult), PQresultErrorMessage(CON_RESULT(_con)));
00429 db_free_result(*_r);
00430 *_r = 0;
00431 rc = -3;
00432 break;
00433
00434 case PGRES_EMPTY_QUERY:
00435
00436 case PGRES_NONFATAL_ERROR:
00437
00438 case PGRES_COPY_OUT:
00439 case PGRES_COPY_IN:
00440
00441 case PGRES_BAD_RESPONSE:
00442 default:
00443 LM_ERR("probable invalid query, execution aborted\n");
00444 LM_ERR("driver message: %s, %s\n", PQresStatus(pqresult), PQresultErrorMessage(CON_RESULT(_con)));
00445 db_free_result(*_r);
00446 *_r = 0;
00447 rc = -4;
00448 break;
00449 }
00450
00451 done:
00452 db_postgres_free_query(_con);
00453 return (rc);
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 int db_postgres_insert(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v,
00466 const int _n)
00467 {
00468 db_res_t* _r = NULL;
00469
00470 int tmp = db_do_insert(_h, _k, _v, _n, db_postgres_val2str, db_postgres_submit_query);
00471
00472 if (db_postgres_store_result(_h, &_r) != 0)
00473 LM_WARN("unexpected result returned");
00474
00475 if (_r)
00476 db_free_result(_r);
00477
00478 return tmp;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 int db_postgres_delete(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
00492 const db_val_t* _v, const int _n)
00493 {
00494 db_res_t* _r = NULL;
00495 int tmp = db_do_delete(_h, _k, _o, _v, _n, db_postgres_val2str,
00496 db_postgres_submit_query);
00497
00498 if (db_postgres_store_result(_h, &_r) != 0)
00499 LM_WARN("unexpected result returned");
00500
00501 if (_r)
00502 db_free_result(_r);
00503
00504 return tmp;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 int db_postgres_update(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
00521 const db_val_t* _v, const db_key_t* _uk, const db_val_t* _uv, const int _n,
00522 const int _un)
00523 {
00524 db_res_t* _r = NULL;
00525 int tmp = db_do_update(_h, _k, _o, _v, _uk, _uv, _n, _un, db_postgres_val2str,
00526 db_postgres_submit_query);
00527
00528 if (db_postgres_store_result(_h, &_r) != 0)
00529 LM_WARN("unexpected result returned");
00530
00531 if (_r)
00532 db_free_result(_r);
00533
00534 return tmp;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544 int db_postgres_use_table(db_con_t* _con, const str* _t)
00545 {
00546 return db_use_table(_con, _t);
00547 }