* dbse_exec_pgsql * */
| 451 | * |
| 452 | */ |
| 453 | static void dbse_exec_pgsql(char *sqlquery, struct context *cnt) |
| 454 | { |
| 455 | #ifdef HAVE_PGSQL |
| 456 | if (mystreq(cnt->conf.database_type, "postgresql") && cnt->database_pgsql) { |
| 457 | PGresult *res; |
| 458 | ExecStatusType estat; |
| 459 | PostgresPollingStatusType pstat; |
| 460 | |
| 461 | if (cnt->eid_db_format == dbeid_recovery) { |
| 462 | /* lost DB session recovery pending */ |
| 463 | pstat = PQresetPoll(cnt->database_pgsql); |
| 464 | if (pstat == PGRES_POLLING_OK) { |
| 465 | MOTION_LOG(WRN, TYPE_DB, NO_ERRNO |
| 466 | ,_("Re-connected to PostgreSQL database '%s'") |
| 467 | ,cnt->conf.database_dbname); |
| 468 | cnt->eid_db_format = dbeid_undetermined; /* reinit eid logic */ |
| 469 | } else if (pstat == PGRES_POLLING_FAILED) { |
| 470 | cnt->eid_db_format = dbeid_rec_fail; /* retry PGresetStart() */ |
| 471 | } else { /* session recovery in process but not complete */ |
| 472 | return; /* discard this sqlquery; check again on next one */ |
| 473 | } |
| 474 | } |
| 475 | |
| 476 | /* attempt sqlquery unless previous DB session break recovery failed */ |
| 477 | if (cnt->eid_db_format > dbeid_recovery) { |
| 478 | MOTION_LOG(DBG, TYPE_DB, NO_ERRNO, _("Executing PostgreSQL query")); |
| 479 | res = PQexec(cnt->database_pgsql, sqlquery); |
| 480 | estat = PQresultStatus(res); |
| 481 | } else { |
| 482 | res = NULL; /* skip PQclear() below */ |
| 483 | estat = PGRES_NONFATAL_ERROR; |
| 484 | } |
| 485 | |
| 486 | if (PQstatus(cnt->database_pgsql) != PGSQL_CONNECTION_OK) { /* DB session break! */ |
| 487 | /* Non-blocking broken session recovery (PGSQL Doc.sec.32.1; PGSQL>v9, 33.1) |
| 488 | * Note: to avoid blocking, each sqlquery during a session break is discarded. */ |
| 489 | if (cnt->eid_db_format != dbeid_rec_fail) { /* log only first attempt */ |
| 490 | MOTION_LOG(ERR, TYPE_DB, NO_ERRNO |
| 491 | ,_("Attempting reconnect to PostgreSQL database '%s': %s") |
| 492 | ,cnt->conf.database_dbname, PQerrorMessage(cnt->database_pgsql)); |
| 493 | } |
| 494 | if (PQresetStart(cnt->database_pgsql)) { /* reset request delivered */ |
| 495 | cnt->eid_db_format = dbeid_recovery; /* suspend SQL operations */ |
| 496 | } else { /* reset request fails if PGSQL server is (temporarily?) unreachable */ |
| 497 | cnt->eid_db_format = dbeid_rec_fail; /* try again next sqlquery */ |
| 498 | } |
| 499 | } else if (!(estat == PGRES_COMMAND_OK || estat == PGRES_TUPLES_OK)) { |
| 500 | MOTION_LOG(ERR, TYPE_DB, SHOW_ERRNO, _("PGSQL query failed: [%s] %s %s"), |
| 501 | sqlquery, PQresStatus(PQresultStatus(res)), PQresultErrorMessage(res)); |
| 502 | } |
| 503 | if (res) { |
| 504 | PQclear(res); |
| 505 | } |
| 506 | } |
| 507 | #else |
| 508 | (void)sqlquery; |
| 509 | (void)cnt; |
| 510 | #endif /* HAVE_PGSQL */ |
no test coverage detected