mirror of
https://github.com/Motion-Project/motion.git
synced 2026-03-05 06:46:23 -05:00
621 lines
24 KiB
C++
621 lines
24 KiB
C++
/*
|
|
* This file is part of MotionPlus.
|
|
*
|
|
* MotionPlus is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* MotionPlus is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with MotionPlus. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* Copyright 2020 MotionMrDave@gmail.com
|
|
*/
|
|
|
|
|
|
#include "motionplus.hpp"
|
|
#include "conf.hpp"
|
|
#include "util.hpp"
|
|
#include "logger.hpp"
|
|
#include "dbse.hpp"
|
|
|
|
/*Edits to validate parms for database use */
|
|
static int dbse_global_edits(struct ctx_cam **cam_list){
|
|
|
|
int retcd = 0;
|
|
|
|
if (cam_list[0]->conf->database_dbname == ""){
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Invalid database name"));
|
|
retcd = -1;
|
|
}
|
|
if ((((cam_list[0]->conf->database_type == "mysql")) ||
|
|
((cam_list[0]->conf->database_type == "mariadb")) ||
|
|
((cam_list[0]->conf->database_type == "pgsql"))) &&
|
|
(cam_list[0]->conf->database_port == 0)){
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Must specify database port for mysql/mariadb/pgsql"));
|
|
retcd = -1;
|
|
}
|
|
|
|
if (retcd == -1){
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Database functionality disabled."));
|
|
cam_list[0]->conf->database_type = "";
|
|
}
|
|
|
|
return retcd;
|
|
|
|
}
|
|
|
|
void dbse_global_deinit(struct ctx_cam **cam_list){
|
|
|
|
int indx;
|
|
|
|
#if defined(HAVE_MYSQL)
|
|
if (cam_list[0]->conf->database_type != "") {
|
|
if ((cam_list[0]->conf->database_type == "mysql")) {
|
|
MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO, _("Closing MYSQL"));
|
|
mysql_library_end();
|
|
}
|
|
}
|
|
#else
|
|
(void)cam_list;
|
|
#endif /* HAVE_MYSQL */
|
|
|
|
#if defined(HAVE_MARIADB)
|
|
if (cam_list[0]->conf->database_type != "") {
|
|
if ((cam_list[0]->conf->database_type == "mariadb")) {
|
|
MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO, _("Closing MYSQL"));
|
|
mysql_library_end();
|
|
}
|
|
}
|
|
#else
|
|
(void)cam_list;
|
|
#endif /* HAVE_MYSQL */
|
|
|
|
indx = 0;
|
|
while (cam_list[indx] != NULL){
|
|
if (cam_list[indx]->dbse != NULL) free(cam_list[indx]->dbse);
|
|
cam_list[indx]->dbse = NULL;
|
|
indx++;
|
|
}
|
|
|
|
}
|
|
|
|
void dbse_global_init(struct ctx_cam **cam_list){
|
|
int indx;
|
|
|
|
indx = 0;
|
|
while (cam_list[indx] != NULL){
|
|
cam_list[indx]->dbse = (struct ctx_dbse *)mymalloc(sizeof(struct ctx_dbse));
|
|
indx++;
|
|
}
|
|
|
|
if (cam_list[0]->conf->database_type != "") {
|
|
if (dbse_global_edits(cam_list) == -1) return;
|
|
|
|
MOTION_LOG(DBG, TYPE_DB, NO_ERRNO,_("Initializing database"));
|
|
/* Initialize all the database items */
|
|
#if defined(HAVE_MYSQL)
|
|
if ((cam_list[0]->conf->database_type == "mysql")) {
|
|
if (mysql_library_init(0, NULL, NULL)) {
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Could not initialize database %s")
|
|
,cam_list[0]->conf->database_type.c_str());
|
|
cam_list[0]->conf->database_type = "";
|
|
return;
|
|
}
|
|
}
|
|
#endif /* HAVE_MYSQL */
|
|
|
|
#if defined(HAVE_MARIADB)
|
|
if ((cam_list[0]->conf->database_type == "mariadb")) {
|
|
if (mysql_library_init(0, NULL, NULL)) {
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Could not initialize database %s")
|
|
,cam_list[0]->conf->database_type.c_str());
|
|
cam_list[0]->conf->database_type = "";
|
|
return;
|
|
}
|
|
}
|
|
#endif /* HAVE_MARIADB */
|
|
|
|
#ifdef HAVE_SQLITE3
|
|
/* database_sqlite3 == NULL if not changed causes each thread to create their own
|
|
* sqlite3 connection this will only happens when using a non-threaded sqlite version */
|
|
cam_list[0]->dbse->database_sqlite3=NULL;
|
|
if ((cam_list[0]->conf->database_type == "sqlite3") &&
|
|
(cam_list[0]->conf->database_dbname != "")) {
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO
|
|
,_("SQLite3 Database filename %s")
|
|
,cam_list[0]->conf->database_dbname.c_str());
|
|
|
|
int thread_safe = sqlite3_threadsafe();
|
|
if (thread_safe > 0) {
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO, _("SQLite3 is threadsafe"));
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO, _("SQLite3 serialized %s")
|
|
,(sqlite3_config(SQLITE_CONFIG_SERIALIZED)?_("FAILED"):_("SUCCESS")));
|
|
if (sqlite3_open(cam_list[0]->conf->database_dbname.c_str(), &cam_list[0]->dbse->database_sqlite3) != SQLITE_OK) {
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Can't open database %s : %s")
|
|
,cam_list[0]->conf->database_dbname.c_str()
|
|
,sqlite3_errmsg(cam_list[0]->dbse->database_sqlite3));
|
|
sqlite3_close(cam_list[0]->dbse->database_sqlite3);
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Could not initialize database %s")
|
|
,cam_list[0]->conf->database_dbname.c_str());
|
|
cam_list[0]->conf->database_type = "";
|
|
return;
|
|
}
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO,_("database_busy_timeout %d msec"),
|
|
cam_list[0]->conf->database_busy_timeout);
|
|
if (sqlite3_busy_timeout(cam_list[0]->dbse->database_sqlite3, cam_list[0]->conf->database_busy_timeout) != SQLITE_OK)
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO,_("database_busy_timeout failed %s")
|
|
,sqlite3_errmsg(cam_list[0]->dbse->database_sqlite3));
|
|
}
|
|
}
|
|
/* Cascade to all threads */
|
|
indx = 1;
|
|
while (cam_list[indx] != NULL) {
|
|
cam_list[indx]->dbse->database_sqlite3 = cam_list[0]->dbse->database_sqlite3;
|
|
indx++;
|
|
}
|
|
|
|
#endif /* HAVE_SQLITE3 */
|
|
}
|
|
}
|
|
|
|
static void dbse_init_mysql(struct ctx_cam *cam){
|
|
|
|
#if defined(HAVE_MYSQL)
|
|
// close database to be sure that we are not leaking
|
|
mysql_close(cam->dbse->database_mysql);
|
|
cam->dbse->database_event_id = 0;
|
|
|
|
cam->dbse->database_mysql = (MYSQL *) mymalloc(sizeof(MYSQL));
|
|
mysql_init(cam->dbse->database_mysql);
|
|
|
|
if (!mysql_real_connect(cam->dbse->database_mysql
|
|
, cam->conf->database_host.c_str(), cam->conf->database_user.c_str()
|
|
, cam->conf->database_password.c_str(), cam->conf->database_dbname.c_str()
|
|
, cam->conf->database_port, NULL, 0)) {
|
|
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Cannot connect to MySQL database %s on host %s with user %s")
|
|
,cam->conf->database_dbname.c_str(), cam->conf->database_host.c_str()
|
|
,cam->conf->database_user.c_str());
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("MySQL error was %s"), mysql_error(cam->dbse->database_mysql));
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Disabling database functionality"));
|
|
dbse_global_deinit(cam->cam_list);
|
|
cam->conf->database_type = "";
|
|
return;
|
|
}
|
|
#if (defined(MYSQL_VERSION_ID)) && (MYSQL_VERSION_ID > 50012)
|
|
my_bool my_true = TRUE;
|
|
mysql_options(cam->dbse->database_mysql, MYSQL_OPT_RECONNECT, &my_true);
|
|
#endif
|
|
#else
|
|
(void)cam; /* Avoid compiler warnings */
|
|
#endif /* HAVE_MYSQL */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
static void dbse_init_mariadb(struct ctx_cam *cam){
|
|
|
|
#if defined(HAVE_MARIADB)
|
|
// close database to be sure that we are not leaking
|
|
mysql_close(cam->dbse->database_mariadb);
|
|
cam->dbse->database_event_id = 0;
|
|
|
|
cam->dbse->database_mariadb = (MYSQL *) mymalloc(sizeof(MYSQL));
|
|
mysql_init(cam->dbse->database_mariadb);
|
|
|
|
if (!mysql_real_connect(cam->dbse->database_mariadb
|
|
, cam->conf->database_host.c_str(), cam->conf->database_user.c_str()
|
|
, cam->conf->database_password.c_str(), cam->conf->database_dbname.c_str()
|
|
, cam->conf->database_port, NULL, 0)) {
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Cannot connect to MySQL database %s on host %s with user %s")
|
|
,cam->conf->database_dbname.c_str(), cam->conf->database_host.c_str()
|
|
,cam->conf->database_user.c_str());
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("MySQL error was %s"), mysql_error(cam->dbse->database_mariadb));
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Disabling database functionality"));
|
|
dbse_global_deinit(cam->cam_list);
|
|
cam->conf->database_type = "";
|
|
return;
|
|
}
|
|
#if (defined(MYSQL_VERSION_ID)) && (MYSQL_VERSION_ID > 50012)
|
|
my_bool my_true = TRUE;
|
|
mysql_options(cam->dbse->database_mariadb, MYSQL_OPT_RECONNECT, &my_true);
|
|
#endif
|
|
#else
|
|
(void)cam; /* Avoid compiler warnings */
|
|
#endif /* HAVE_MARIADB */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
static void dbse_init_sqlite3(struct ctx_cam *cam){
|
|
#ifdef HAVE_SQLITE3
|
|
if (cam->cam_list[0]->dbse->database_sqlite3 != 0) {
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO,_("SQLite3 using shared handle"));
|
|
cam->dbse->database_sqlite3 = cam->cam_list[0]->dbse->database_sqlite3;
|
|
} else {
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO
|
|
,_("SQLite3 Database filename %s"), cam->conf->database_dbname.c_str());
|
|
if (sqlite3_open(cam->conf->database_dbname.c_str(), &cam->dbse->database_sqlite3) != SQLITE_OK) {
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Can't open database %s : %s")
|
|
,cam->conf->database_dbname.c_str(), sqlite3_errmsg(cam->dbse->database_sqlite3));
|
|
sqlite3_close(cam->dbse->database_sqlite3);
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Disabling database functionality"));
|
|
cam->conf->database_type = "";
|
|
return;
|
|
}
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO
|
|
,_("database_busy_timeout %d msec"), cam->conf->database_busy_timeout);
|
|
if (sqlite3_busy_timeout(cam->dbse->database_sqlite3, cam->conf->database_busy_timeout) != SQLITE_OK)
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("database_busy_timeout failed %s")
|
|
,sqlite3_errmsg(cam->dbse->database_sqlite3));
|
|
}
|
|
#else
|
|
(void)cam; /* Avoid compiler warnings */
|
|
#endif /* HAVE_SQLITE3 */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
static void dbse_init_pgsql(struct ctx_cam *cam){
|
|
#ifdef HAVE_PGSQL
|
|
char connstring[255];
|
|
/* Create the connection string.
|
|
* Quote the values so we can have null values (blank)
|
|
*/
|
|
snprintf(connstring, 255,
|
|
"dbname='%s' host='%s' user='%s' password='%s' port='%d'",
|
|
cam->conf->database_dbname.c_str(), /* dbname */
|
|
(cam->conf->database_host=="" ? cam->conf->database_host.c_str() : ""), /* host (may be blank) */
|
|
(cam->conf->database_user=="" ? cam->conf->database_user.c_str() : ""), /* user (may be blank) */
|
|
(cam->conf->database_password=="" ? cam->conf->database_password.c_str() : ""), /* password (may be blank) */
|
|
cam->conf->database_port
|
|
);
|
|
|
|
cam->dbse->database_pg = PQconnectdb(connstring);
|
|
if (PQstatus(cam->dbse->database_pg) == CONNECTION_BAD) {
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Connection to PostgreSQL database '%s' failed: %s")
|
|
,cam->conf->database_dbname.c_str(), PQerrorMessage(cam->dbse->database_pg));
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Disabling database functionality"));
|
|
cam->conf->database_type = "";
|
|
return;
|
|
}
|
|
#else
|
|
(void)cam; /* Avoid compiler warnings */
|
|
#endif /* HAVE_PGSQL */
|
|
|
|
return;
|
|
}
|
|
|
|
void dbse_init(struct ctx_cam *cam){
|
|
|
|
if (cam->conf->database_type != "") {
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO
|
|
,_("Database backend %s"), cam->conf->database_type.c_str());
|
|
if (cam->conf->database_type == "mysql") {
|
|
dbse_init_mysql(cam);
|
|
} else if (cam->conf->database_type == "mariadb") {
|
|
dbse_init_mariadb(cam);
|
|
} else if (cam->conf->database_type == "postgresql") {
|
|
dbse_init_pgsql(cam);
|
|
} else if (cam->conf->database_type == "sqlite3") {
|
|
dbse_init_sqlite3(cam);
|
|
} else {
|
|
MOTION_LOG(NTC, TYPE_DB, NO_ERRNO
|
|
,_("Invalid Database backend %s")
|
|
, cam->conf->database_type.c_str());
|
|
}
|
|
dbse_sqlmask_update(cam);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void dbse_deinit(struct ctx_cam *cam){
|
|
if (cam->conf->database_type != "") {
|
|
MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO, _("Closing database"));
|
|
|
|
#if defined(HAVE_MYSQL)
|
|
if (cam->conf->database_type == "mysql") {
|
|
mysql_close(cam->dbse->database_mysql);
|
|
cam->dbse->database_event_id = 0;
|
|
}
|
|
#endif /* HAVE_MYSQL */
|
|
|
|
#if defined(HAVE_MARIADB)
|
|
if (cam->conf->database_type == "mariadb") {
|
|
mysql_close(cam->dbse->database_mariadb);
|
|
cam->dbse->database_event_id = 0;
|
|
}
|
|
#endif /* HAVE_MYSQL */
|
|
|
|
#ifdef HAVE_PGSQL
|
|
if (cam->conf->database_type == "postgresql") {
|
|
PQfinish(cam->dbse->database_pg);
|
|
}
|
|
#endif /* HAVE_PGSQL */
|
|
|
|
#ifdef HAVE_SQLITE3
|
|
/* Close the SQLite database */
|
|
if (cam->conf->database_type == "sqlite3") {
|
|
sqlite3_close(cam->dbse->database_sqlite3);
|
|
cam->dbse->database_sqlite3 = NULL;
|
|
}
|
|
#endif /* HAVE_SQLITE3 */
|
|
}
|
|
|
|
}
|
|
|
|
void dbse_sqlmask_update(struct ctx_cam *cam){
|
|
/*
|
|
* Set the sql mask file according to the SQL config options
|
|
* We update it for every frame in case the config was updated
|
|
* via remote control.
|
|
*/
|
|
cam->dbse->sql_mask = cam->conf->sql_log_picture * (FTYPE_IMAGE + FTYPE_IMAGE_MOTION) +
|
|
cam->conf->sql_log_snapshot * FTYPE_IMAGE_SNAPSHOT +
|
|
cam->conf->sql_log_movie * (FTYPE_MPEG + FTYPE_MPEG_MOTION) +
|
|
cam->conf->sql_log_timelapse * FTYPE_MPEG_TIMELAPSE;
|
|
|
|
}
|
|
|
|
static void dbse_mysql_exec(char *sqlquery,struct ctx_cam *cam, int save_id) {
|
|
|
|
#if defined(HAVE_MYSQL)
|
|
MOTION_LOG(DBG, TYPE_DB, NO_ERRNO, "Executing mysql query");
|
|
if (mysql_query(cam->dbse->database_mysql, sqlquery) != 0) {
|
|
int error_code = mysql_errno(cam->dbse->database_mysql);
|
|
|
|
MOTION_LOG(ERR, TYPE_DB, SHOW_ERRNO
|
|
,_("Mysql query failed %s error code %d")
|
|
,mysql_error(cam->dbse->database_mysql), error_code);
|
|
/* Try to reconnect ONCE if fails continue and discard this sql query */
|
|
if (error_code >= 2000) {
|
|
// Close connection before start a new connection
|
|
mysql_close(cam->dbse->database_mysql);
|
|
|
|
cam->dbse->database_mysql = (MYSQL *) mymalloc(sizeof(MYSQL));
|
|
mysql_init(cam->dbse->database_mysql);
|
|
|
|
if (!mysql_real_connect(cam->dbse->database_mysql, cam->conf->database_host.c_str(),
|
|
cam->conf->database_user.c_str(), cam->conf->database_password.c_str(),
|
|
cam->conf->database_dbname.c_str(), cam->conf->database_port, NULL, 0)) {
|
|
MOTION_LOG(ALR, TYPE_DB, NO_ERRNO
|
|
,_("Cannot reconnect to MySQL"
|
|
" database %s on host %s with user %s MySQL error was %s"),
|
|
cam->conf->database_dbname.c_str(),
|
|
cam->conf->database_host.c_str(), cam->conf->database_user.c_str(),
|
|
mysql_error(cam->dbse->database_mysql));
|
|
} else {
|
|
MOTION_LOG(INF, TYPE_DB, NO_ERRNO
|
|
,_("Re-Connection to Mysql database '%s' Succeed")
|
|
,cam->conf->database_dbname.c_str());
|
|
if (mysql_query(cam->dbse->database_mysql, sqlquery) != 0) {
|
|
int error_my = mysql_errno(cam->dbse->database_mysql);
|
|
MOTION_LOG(ERR, TYPE_DB, SHOW_ERRNO
|
|
,_("after re-connection Mysql query failed %s error code %d")
|
|
,mysql_error(cam->dbse->database_mysql), error_my);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (save_id) {
|
|
cam->dbse->database_event_id = (unsigned long long) mysql_insert_id(cam->dbse->database_mysql);
|
|
}
|
|
#else
|
|
(void)sqlquery;
|
|
(void)cam;
|
|
(void)save_id;
|
|
#endif /* HAVE_MYSQL HAVE_MARIADB*/
|
|
|
|
}
|
|
|
|
static void dbse_mariadb_exec(char *sqlquery,struct ctx_cam *cam, int save_id) {
|
|
|
|
#if defined(HAVE_MARIADB)
|
|
MOTION_LOG(DBG, TYPE_DB, NO_ERRNO, "Executing mysql query");
|
|
if (mysql_query(cam->dbse->database_mariadb, sqlquery) != 0) {
|
|
int error_code = mysql_errno(cam->dbse->database_mariadb);
|
|
|
|
MOTION_LOG(ERR, TYPE_DB, SHOW_ERRNO
|
|
,_("Mysql query failed %s error code %d")
|
|
,mysql_error(cam->dbse->database_mariadb), error_code);
|
|
/* Try to reconnect ONCE if fails continue and discard this sql query */
|
|
if (error_code >= 2000) {
|
|
// Close connection before start a new connection
|
|
mysql_close(cam->dbse->database_mariadb);
|
|
|
|
cam->dbse->database_mariadb = (MYSQL *) mymalloc(sizeof(MYSQL));
|
|
mysql_init(cam->dbse->database_mariadb);
|
|
|
|
if (!mysql_real_connect(cam->dbse->database_mariadb, cam->conf->database_host.c_str(),
|
|
cam->conf->database_user.c_str(), cam->conf->database_password.c_str(),
|
|
cam->conf->database_dbname.c_str(),cam->conf->database_port, NULL, 0)) {
|
|
MOTION_LOG(ALR, TYPE_DB, NO_ERRNO
|
|
,_("Cannot reconnect to MySQL"
|
|
" database %s on host %s with user %s MySQL error was %s"),
|
|
cam->conf->database_dbname.c_str(),
|
|
cam->conf->database_host.c_str(), cam->conf->database_user.c_str(),
|
|
mysql_error(cam->dbse->database_mariadb));
|
|
} else {
|
|
MOTION_LOG(INF, TYPE_DB, NO_ERRNO
|
|
,_("Re-Connection to Mysql database '%s' Succeed")
|
|
,cam->conf->database_dbname.c_str());
|
|
if (mysql_query(cam->dbse->database_mariadb, sqlquery) != 0) {
|
|
int error_my = mysql_errno(cam->dbse->database_mariadb);
|
|
MOTION_LOG(ERR, TYPE_DB, SHOW_ERRNO
|
|
,_("after re-connection Mysql query failed %s error code %d")
|
|
,mysql_error(cam->dbse->database_mariadb), error_my);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (save_id) {
|
|
cam->dbse->database_event_id = (unsigned long long) mysql_insert_id(cam->dbse->database_mariadb);
|
|
}
|
|
#else
|
|
(void)sqlquery;
|
|
(void)cam;
|
|
(void)save_id;
|
|
#endif /* HAVE_MARIADB*/
|
|
|
|
}
|
|
|
|
static void dbse_pgsql_exec(char *sqlquery,struct ctx_cam *cam, int save_id) {
|
|
#ifdef HAVE_PGSQL
|
|
MOTION_LOG(DBG, TYPE_DB, NO_ERRNO, "Executing postgresql query");
|
|
PGresult *res;
|
|
|
|
res = PQexec(cam->dbse->database_pg, sqlquery);
|
|
|
|
if (PQstatus(cam->dbse->database_pg) == CONNECTION_BAD) {
|
|
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Connection to PostgreSQL database '%s' failed: %s")
|
|
,cam->conf->database_dbname.c_str(), PQerrorMessage(cam->dbse->database_pg));
|
|
|
|
// This function will close the connection to the server and attempt to reestablish a new connection to the same server,
|
|
// using all the same parameters previously used. This may be useful for error recovery if a working connection is lost
|
|
PQreset(cam->dbse->database_pg);
|
|
|
|
if (PQstatus(cam->dbse->database_pg) == CONNECTION_BAD) {
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO
|
|
,_("Re-Connection to PostgreSQL database '%s' failed: %s")
|
|
,cam->conf->database_dbname.c_str(), PQerrorMessage(cam->dbse->database_pg));
|
|
} else {
|
|
MOTION_LOG(INF, TYPE_DB, NO_ERRNO
|
|
,_("Re-Connection to PostgreSQL database '%s' Succeed")
|
|
,cam->conf->database_dbname.c_str());
|
|
}
|
|
|
|
} else if (!(PQresultStatus(res) == PGRES_COMMAND_OK || PQresultStatus(res) == PGRES_TUPLES_OK)) {
|
|
MOTION_LOG(ERR, TYPE_DB, SHOW_ERRNO, "PGSQL query failed: [%s] %s %s",
|
|
sqlquery, PQresStatus(PQresultStatus(res)), PQresultErrorMessage(res));
|
|
}
|
|
if (save_id) {
|
|
//ToDO: Find the equivalent option for pgsql
|
|
cam->dbse->database_event_id = 0;
|
|
}
|
|
|
|
PQclear(res);
|
|
#else
|
|
(void)sqlquery;
|
|
(void)cam;
|
|
(void)save_id;
|
|
#endif /* HAVE_PGSQL */
|
|
|
|
}
|
|
|
|
static void dbse_sqlite3_exec(char *sqlquery,struct ctx_cam *cam, int save_id) {
|
|
#ifdef HAVE_SQLITE3
|
|
int res;
|
|
char *errmsg = 0;
|
|
MOTION_LOG(DBG, TYPE_DB, NO_ERRNO, "Executing sqlite query");
|
|
res = sqlite3_exec(cam->dbse->database_sqlite3, sqlquery, NULL, 0, &errmsg);
|
|
if (res != SQLITE_OK ) {
|
|
MOTION_LOG(ERR, TYPE_DB, NO_ERRNO, _("SQLite error was %s"), errmsg);
|
|
sqlite3_free(errmsg);
|
|
}
|
|
if (save_id) {
|
|
//ToDO: Find the equivalent option for sqlite3
|
|
cam->dbse->database_event_id = 0;
|
|
}
|
|
#else
|
|
(void)sqlquery;
|
|
(void)cam;
|
|
(void)save_id;
|
|
#endif /* HAVE_SQLITE3 */
|
|
}
|
|
|
|
void dbse_firstmotion(struct ctx_cam *cam){
|
|
|
|
char sqlquery[PATH_MAX];
|
|
|
|
mystrftime(cam, sqlquery, sizeof(sqlquery), cam->conf->sql_query_start.c_str(),
|
|
&cam->current_image->imgts, NULL, 0);
|
|
|
|
if (strlen(sqlquery) <= 0) {
|
|
MOTION_LOG(WRN, TYPE_DB, NO_ERRNO, "Ignoring empty sql query");
|
|
return;
|
|
}
|
|
|
|
if (cam->conf->database_type == "mysql") {
|
|
dbse_mysql_exec(sqlquery, cam, 1);
|
|
} else if (cam->conf->database_type == "mariadb") {
|
|
dbse_mariadb_exec(sqlquery, cam, 1);
|
|
} else if (cam->conf->database_type == "postgresql") {
|
|
dbse_pgsql_exec(sqlquery, cam, 1);
|
|
} else if (cam->conf->database_type == "sqlite3") {
|
|
dbse_sqlite3_exec(sqlquery, cam, 1);
|
|
}
|
|
|
|
}
|
|
|
|
void dbse_newfile(struct ctx_cam *cam, char *filename, int sqltype, struct timespec *ts1) {
|
|
char sqlquery[PATH_MAX];
|
|
|
|
mystrftime(cam, sqlquery, sizeof(sqlquery), cam->conf->sql_query.c_str(),
|
|
ts1, filename, sqltype);
|
|
|
|
if (strlen(sqlquery) <= 0) {
|
|
MOTION_LOG(WRN, TYPE_DB, NO_ERRNO, "Ignoring empty sql query");
|
|
return;
|
|
}
|
|
|
|
if (cam->conf->database_type == "mysql") {
|
|
dbse_mysql_exec(sqlquery, cam, 0);
|
|
} else if (cam->conf->database_type == "mariadb") {
|
|
dbse_mariadb_exec(sqlquery, cam, 0);
|
|
} else if (cam->conf->database_type == "postgresql") {
|
|
dbse_pgsql_exec(sqlquery, cam, 0);
|
|
} else if (cam->conf->database_type == "sqlite3") {
|
|
dbse_sqlite3_exec(sqlquery, cam, 0);
|
|
}
|
|
|
|
}
|
|
|
|
void dbse_fileclose(struct ctx_cam *cam, char *filename, int sqltype, struct timespec *ts1) {
|
|
|
|
char sqlquery[PATH_MAX];
|
|
|
|
mystrftime(cam, sqlquery, sizeof(sqlquery), cam->conf->sql_query_stop.c_str(),
|
|
ts1, filename, sqltype);
|
|
|
|
if (cam->conf->database_type == "mysql") {
|
|
dbse_mysql_exec(sqlquery, cam, 0);
|
|
} else if (cam->conf->database_type == "mariadb") {
|
|
dbse_mariadb_exec(sqlquery, cam, 0);
|
|
} else if (cam->conf->database_type == "postgresql") {
|
|
dbse_pgsql_exec(sqlquery, cam, 0);
|
|
} else if (cam->conf->database_type == "sqlite3") {
|
|
dbse_sqlite3_exec(sqlquery, cam, 0);
|
|
}
|
|
|
|
}
|