/** * Update a status value * * @param dbi a valid DBI connection (no ping is done) * @param key the status value key * @param value the status value saved */ void tagsistant_save_status(dbi_conn dbi, gchar *key, gchar *value) { gchar *query = NULL; dbg('s', LOG_ERR, "Updating status %s => %s", key, value); query = g_strdup_printf("delete from status where state = '%s'", key); if (!query) return; dbi_result result = dbi_conn_query(dbi, query); g_free(query); if (!result) { const char *errmsg = NULL; dbi_conn_error(dbi, &errmsg); if (errmsg) dbg('s', LOG_ERR, "Error saving status %s => %s: %s", key, value, errmsg); return; } query = g_strdup_printf("insert into status values ('%s', '%s')", key, value); if (!query) return; result = dbi_conn_query(dbi, query); g_free(query); if (!result) { const char *errmsg = NULL; dbi_conn_error(dbi, &errmsg); if (errmsg) dbg('s', LOG_ERR, "Error saving status %s => %s: %s", key, value, errmsg); } }
int dbiw_set_auto_commit(db_wrap * self, int set) { dbi_result dbir; DB_DECL(DB_WRAP_E_BAD_ARG); if (set) { dbir = dbi_conn_query(conn, "SET AUTOCOMMIT = 1"); } else { dbir = dbi_conn_query(conn, "SET AUTOCOMMIT = 0"); } if (dbir) dbi_result_free(dbir); return 0; }
dbi_result db_rawquery(dbi_conn conn, int log_dupes, const char *qry) { dbi_result result; if (debug > 4) { LOGRAW(LOG_DEBUG, qry); } result = dbi_conn_query(conn, qry); if (dbi_conn_error_flag(conn)) { const char *errmsg; dbi_conn_error(conn, &errmsg); /* switch (mysql_errno(mysql)) { case ER_DUP_ENTRY: if (!log_dupes) break; default: */ LOG(LOG_WARNING, "%s: %s", qry, errmsg); /* break; } */ return(NULL); } return(result); }
/* Run a mysql insert query and return a categorized error or success */ static logsql_query_ret log_sql_dbi_query(request_rec *r,logsql_dbconnection *db, const char *query) { const char *error; dbi_result result; dbi_conn_rec *dblink = db->handle; if (!dblink->conn) { return LOGSQL_QUERY_NOLINK; } /* Run the query */ if ((result = dbi_conn_query(dblink->conn, query))) { return LOGSQL_QUERY_SUCCESS; } /* Check to see if the error is "nonexistent table" */ dbi_conn_error(dblink->conn, &error); log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "DBI Error: %s", error); /* if (real_error == ER_NO_SUCH_TABLE) { log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query"); return LOGSQL_QUERY_NOTABLE; }*/ return LOGSQL_QUERY_FAIL; }
static int safe_dbi_query(ftpd_dbi_rest * mydbi_res, dbi_result * res, const request_rec * r, const char *query) { int err_num = 0; const char *err_str; int error = 1; *res = (dbi_result) dbi_conn_query(mydbi_res->conn, query); /* logging complete sql queries is bad. I personaly * uncomment this for some debuging... but even * APLOG_DEBUG isn't good for this. */ /* ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, * "[mod_ftpd_dbi.c] SQL Query: %s", query); */ if (res == NULL) { err_num = dbi_conn_error(mydbi_res->conn, (const char **)&err_str); ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "[mod_ftpd_dbi.c] SQL Query Failed. DBI said: (%d) %s", err_num, err_str); } else { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "[mod_ftpd_dbi.c] Query Result is good."); error = 0; } return error; }
/** * afsql_dd_run_query: * * Run an SQL query on the connected database. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_run_query(AFSqlDestDriver *self, const gchar *query, gboolean silent, dbi_result *result) { dbi_result db_res; msg_debug("Running SQL query", evt_tag_str("query", query), NULL); db_res = dbi_conn_query(self->dbi_ctx, query); if (!db_res) { const gchar *dbi_error; if (!silent) { dbi_conn_error(self->dbi_ctx, &dbi_error); msg_error("Error running SQL query", evt_tag_str("type", self->type), evt_tag_str("host", self->host), evt_tag_str("port", self->port), evt_tag_str("user", self->user), evt_tag_str("database", self->database), evt_tag_str("error", dbi_error), evt_tag_str("query", query), NULL); } return FALSE; } if (result) *result = db_res; else dbi_result_free(db_res); return TRUE; }
gboolean tagsistant_wal_apply_line(dbi_conn dbi, const gchar *line, const gchar *last_tstamp) { gboolean retcode = FALSE; GMatchInfo *info; if (!g_regex_match(wal_pattern, line, 0, &info)) { dbg('s', LOG_ERR, "WAL: malformed log entry %s", line); return (FALSE); } gchar *tstamp = g_match_info_fetch(info, 1); gchar *statement = g_match_info_fetch(info, 2); if (strcmp(tstamp, last_tstamp) > 0) { /* * execute the statement */ dbi_result result = dbi_conn_query(dbi, statement); if (!result) { const char *errmsg = NULL; dbi_conn_error(dbi, &errmsg); if (errmsg) dbg('s', LOG_ERR, "WAL: Error syncing [%s]: %s", statement, errmsg); } else { retcode = TRUE; } } else { retcode = TRUE; } g_free(tstamp); g_free(statement); g_match_info_free(info); return (retcode); }
swd::blacklist_filters swd::database::get_blacklist_filters() { swd::log::i()->send(swd::notice, "Get blacklist filters from db"); ensure_connection(); boost::unique_lock<boost::mutex> scoped_lock(dbi_mutex_); dbi_result res = dbi_conn_query(conn_, "SELECT id, impact, rule FROM blacklist_filters"); if (!res) { throw swd::exceptions::database_exception("Can't execute blacklist_filters query"); } swd::blacklist_filters filters; while (dbi_result_next_row(res)) { swd::blacklist_filter_ptr filter(new swd::blacklist_filter()); filter->set_id(dbi_result_get_uint(res, "id")); filter->set_impact(dbi_result_get_uint(res, "impact")); filter->set_regex(dbi_result_get_string(res, "rule")); filters.push_back(filter); } dbi_result_free(res); return filters; }
/** @brief Disconnect from the database. This function is called when the server drone is about to terminate. */ void osrfAppChildExit() { osrfLogDebug( OSRF_LOG_MARK, "Child is exiting, disconnecting from database..." ); if ( dbhandle ) { dbi_conn_query( dbhandle, "ROLLBACK;" ); dbi_conn_close( dbhandle ); dbhandle = NULL; } }
/* checks mysql sql_options and adjusts if necessary */ static void adjust_sql_options (dbi_conn connection) { dbi_result result = dbi_conn_query( connection, "SELECT @@sql_mode"); if (result == nullptr) { const char* errmsg; int err = dbi_conn_error(connection, &errmsg); PERR("Unable to read sql_mode %d : %s", err, errmsg); return; } dbi_result_first_row(result); std::string str{dbi_result_get_string_idx(result, 1)}; dbi_result_free(result); if (str.empty()) { const char* errmsg; int err = dbi_conn_error(connection, &errmsg); if (err) PERR("Unable to get sql_mode %d : %s", err, errmsg); else PINFO("Sql_mode isn't set."); return; } PINFO("Initial sql_mode: %s", str.c_str()); if(str.find(SQL_OPTION_TO_REMOVE) == std::string::npos) return; std::string adjusted_str{adjust_sql_options_string(str)}; PINFO("Setting sql_mode to %s", adjusted_str.c_str()); std::string set_str{"SET sql_mode=" + std::move(adjusted_str)}; dbi_result set_result = dbi_conn_query(connection, set_str.c_str()); if (set_result) { dbi_result_free(set_result); } else { const char* errmsg; int err = dbi_conn_error(connection, &errmsg); PERR("Unable to set sql_mode %d : %s", err, errmsg); } }
int dbiw_commit(db_wrap * self) { dbi_result dbir; DB_DECL(DB_WRAP_E_BAD_ARG); dbir = dbi_conn_query(conn, "COMMIT"); if (dbir) dbi_result_free(dbir); return 0; }
int main (int argc, char *argv[]) { dbi_conn conn; dbi_result result; const char *err_msg; int err_code; if (argc < 2) { fprintf (stderr, "%s: Need a libdir as argument!\n", argv[0]); return 1; } dbi_initialize (argv[1]); conn = dbi_conn_new ("null"); dbi_conn_connect (conn); /* * Queries */ result = dbi_conn_query (conn, "COMMIT"); assert (result != NULL); dbi_result_free (result); dbi_conn_set_option_numeric (conn, "null.error.commit", 1); result = dbi_conn_query (conn, "COMMIT"); assert (result == NULL); dbi_conn_set_option_numeric (conn, "null.error.commit", 0); result = dbi_conn_query (conn, "COMMIT"); assert (result != NULL); dbi_result_free (result); /* * Normal queries */ result = dbi_conn_query (conn, "SELECT * FROM DUAL"); assert (result != NULL); dbi_result_free (result); dbi_conn_set_option_numeric (conn, "null.error.query", 1); result = dbi_conn_query (conn, "SELECT * FROM DUAL"); assert (result == NULL); dbi_conn_set_option_numeric (conn, "null.error.query", 0); result = dbi_conn_query (conn, "SELECT * FROM DUAL"); assert (result != NULL); dbi_result_free (result); /* * Cleanup */ dbi_conn_close (conn); dbi_shutdown (); return 0; }
/* The following function writes the current log entry * to an established database connection. */ rsRetVal writeDB(uchar *psz, instanceData *pData) { DEFiRet; dbi_result dbiRes = NULL; ASSERT(psz != NULL); ASSERT(pData != NULL); /* see if we are ready to proceed */ if(pData->conn == NULL) { CHKiRet(initConn(pData, 0)); } /* try insert */ if((dbiRes = dbi_conn_query(pData->conn, (const char*)psz)) == NULL) { /* error occured, try to re-init connection and retry */ closeConn(pData); /* close the current handle */ CHKiRet(initConn(pData, 0)); /* try to re-open */ if((dbiRes = dbi_conn_query(pData->conn, (const char*)psz)) == NULL) { /* re-try insert */ /* we failed, giving up for now */ reportDBError(pData, 0); closeConn(pData); /* free ressources */ ABORT_FINALIZE(RS_RET_SUSPENDED); } } finalize_it: if(iRet == RS_RET_OK) { pData->uLastDBErrno = 0; /* reset error for error supression */ } if(dbiRes != NULL) dbi_result_free(dbiRes); RETiRet; }
static GSM_Error SMSDDBI_Query(GSM_SMSDConfig * Config, const char *query, SQL_result * res) { const char *msg; int rc; res->dbi = NULL; SMSD_Log(DEBUG_SQL, Config, "Execute SQL: %s", query); res->dbi = dbi_conn_query(Config->conn.dbi, query); if (res->dbi != NULL) return ERR_NONE; SMSD_Log(DEBUG_INFO, Config, "SQL failed: %s", query); /* Black magic to decide whether we should bail out or attempt to retry */ rc = dbi_conn_error(Config->conn.dbi, &msg); if (rc != -1) { SMSD_Log(DEBUG_INFO, Config, "SQL failure: %s", msg); if (strstr(msg, "syntax") != NULL) { return ERR_SQL; } if (strstr(msg, "violation") != NULL) { return ERR_SQL; } if (strstr(msg, "violates") != NULL) { return ERR_SQL; } if (strstr(msg, "SQL error") != NULL) { return ERR_SQL; } if (strstr(msg, "duplicate") != NULL) { return ERR_SQL; } if (strstr(msg, "unique") != NULL) { return ERR_SQL; } if (strstr(msg, "need to rewrite") != NULL) { return ERR_SQL; } if (strstr(msg, "locked") != NULL) { return ERR_DB_TIMEOUT; } } return ERR_DB_TIMEOUT; }
/** @brief Disconnect from the database. This function is called when the server drone is about to terminate. */ void osrfAppChildExit( void ) { osrfLogDebug(OSRF_LOG_MARK, "Child is exiting, disconnecting from database..."); int same = 0; if (writehandle == dbhandle) same = 1; if (writehandle) { dbi_conn_query(writehandle, "ROLLBACK;"); dbi_conn_close(writehandle); writehandle = NULL; } if (dbhandle && !same) dbi_conn_close(dbhandle); // XXX add cleanup of readHandles whenever that gets used return; }
template<> StrVec GncDbiProviderImpl<DbType::DBI_SQLITE>::get_index_list (dbi_conn conn) { StrVec retval; const char* errmsg; dbi_result result = dbi_conn_query (conn, "SELECT name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_autoindex%'"); if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE) { PWARN ("Index Table Retrieval Error: %s\n", errmsg); return retval; } while (dbi_result_next_row (result) != 0) { std::string index_name {dbi_result_get_string_idx (result, 1)}; retval.push_back(index_name); } dbi_result_free (result); return retval; }
int dbiw_query_result(db_wrap * self, char const * sql, size_t len, db_wrap_result ** tgt) { /* This impl does not use the len param, but it's in the interface because i expect some other wrappers to need it. */ DB_DECL(DB_WRAP_E_BAD_ARG); if (! sql || !*sql || !len || !tgt) return DB_WRAP_E_BAD_ARG; dbi_result dbir = dbi_conn_query(conn, sql); if (! dbir) return DB_WRAP_E_CHECK_DB_ERROR; db_wrap_result * wres = dbiw_res_alloc(); if (! wres) { dbi_result_free(dbir); return DB_WRAP_E_ALLOC_ERROR; } wres->impl.data = dbir; /*MARKER("dbi_wrap_result@%p, dbi_result @%p\n", (void const *)wres, (void const *)dbir);*/ *tgt = wres; return 0; }
template<> StrVec GncDbiProviderImpl<DbType::DBI_PGSQL>::get_index_list (dbi_conn conn) { StrVec retval; const char* errmsg; PINFO ("Retrieving postgres index list\n"); auto result = dbi_conn_query (conn, "SELECT relname FROM pg_class AS a INNER JOIN pg_index AS b ON (b.indexrelid = a.oid) INNER JOIN pg_namespace AS c ON (a.relnamespace = c.oid) WHERE reltype = '0' AND indisprimary = 'f' AND nspname = 'public'"); if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE) { PWARN("Index Table Retrieval Error: %s\n", errmsg); return retval; } while (dbi_result_next_row (result) != 0) { std::string index_name {dbi_result_get_string_idx (result, 1)}; retval.push_back(index_name); } dbi_result_free (result); return retval; }
int main() { dbi_conn conn; dbi_result result; int v; dbi_initialize(NULL); conn = dbi_conn_new("pgsql"); dbi_conn_set_option(conn, "host", "localhost"); dbi_conn_set_option(conn, "username", "mud"); dbi_conn_set_option(conn, "dbname", "mud"); if ( (v = dbi_conn_connect(conn)) < 0 ) { const char* p; dbi_conn_error(conn, &p); printf(" :: %s\n", p); return 0; } else printf("%d\n", v); result = dbi_conn_query(conn, "select * from account"); }
/* Create table table_name of type table_type. */ static logsql_table_ret log_sql_dbi_create(request_rec *r, logsql_dbconnection *db, logsql_tabletype table_type, const char *table_name) { dbi_result result; const char *driver = apr_table_get(db->parms,"driver"); const char *tabletype = apr_table_get(db->parms,"tabletype"); char *type_suffix = NULL; char *create_prefix = "create table if not exists `"; char *create_suffix = NULL; char *create_sql; dbi_conn_rec *dblink = db->handle; /* if (!global_config.createtables) { return APR_SUCCESS; }*/ switch (table_type) { case LOGSQL_TABLE_ACCESS: create_suffix = "` (id char(19),\ agent varchar(255),\ bytes_sent int unsigned,\ child_pid smallint unsigned,\ cookie varchar(255),\ machine_id varchar(25),\ request_file varchar(255),\ referer varchar(255),\ remote_host varchar(50),\ remote_logname varchar(50),\ remote_user varchar(50),\ request_duration smallint unsigned,\ request_line varchar(255),\ request_method varchar(10),\ request_protocol varchar(10),\ request_time char(28),\ request_uri varchar(255),\ request_args varchar(255),\ server_port smallint unsigned,\ ssl_cipher varchar(25),\ ssl_keysize smallint unsigned,\ ssl_maxkeysize smallint unsigned,\ status smallint unsigned,\ time_stamp int unsigned,\ virtual_host varchar(255))"; break; case LOGSQL_TABLE_COOKIES: case LOGSQL_TABLE_HEADERSIN: case LOGSQL_TABLE_HEADERSOUT: case LOGSQL_TABLE_NOTES: create_suffix = "` (id char(19),\ item varchar(80),\ val varchar(80))"; break; } if (tabletype && !strcmp(driver,"mysql")) { type_suffix = apr_pstrcat(r->pool, " TYPE=", tabletype, NULL); } /* Find memory long enough to hold the whole CREATE string + \0 */ create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix, type_suffix, NULL); log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql); if (!dblink) { return LOGSQL_QUERY_NOLINK; } /* Run the create query */ if (!(result = dbi_conn_query(dblink, create_sql))) { const char *error; dbi_conn_error(dblink->conn, &error); log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "DBI Error: %s", error); return LOGSQL_TABLE_FAIL; } return LOGSQL_TABLE_SUCCESS; }
static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */ udb_query_t *q, udb_query_preparation_area_t *prep_area) { const char *statement; dbi_result res; size_t column_num; char **column_names; char **column_values; int status; size_t i; /* Macro that cleans up dynamically allocated memory and returns the * specified status. */ #define BAIL_OUT(status) \ if (column_names != NULL) { sfree (column_names[0]); sfree (column_names); } \ if (column_values != NULL) { sfree (column_values[0]); sfree (column_values); } \ if (res != NULL) { dbi_result_free (res); res = NULL; } \ return (status) column_names = NULL; column_values = NULL; statement = udb_query_get_statement (q); assert (statement != NULL); res = dbi_conn_query (db->connection, statement); if (res == NULL) { char errbuf[1024]; ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): " "dbi_conn_query failed: %s", db->name, udb_query_get_name (q), cdbi_strerror (db->connection, errbuf, sizeof (errbuf))); BAIL_OUT (-1); } else /* Get the number of columns */ { unsigned int db_status; db_status = dbi_result_get_numfields (res); if (db_status == DBI_FIELD_ERROR) { char errbuf[1024]; ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): " "dbi_result_get_numfields failed: %s", db->name, udb_query_get_name (q), cdbi_strerror (db->connection, errbuf, sizeof (errbuf))); BAIL_OUT (-1); } column_num = (size_t) db_status; DEBUG ("cdbi_read_database_query (%s, %s): There are %zu columns.", db->name, udb_query_get_name (q), column_num); } /* Allocate `column_names' and `column_values'. {{{ */ column_names = calloc (column_num, sizeof (*column_names)); if (column_names == NULL) { ERROR ("dbi plugin: calloc failed."); BAIL_OUT (-1); } column_names[0] = calloc (column_num, DATA_MAX_NAME_LEN); if (column_names[0] == NULL) { ERROR ("dbi plugin: calloc failed."); BAIL_OUT (-1); } for (i = 1; i < column_num; i++) column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN; column_values = calloc (column_num, sizeof (*column_values)); if (column_values == NULL) { ERROR ("dbi plugin: calloc failed."); BAIL_OUT (-1); } column_values[0] = calloc (column_num, DATA_MAX_NAME_LEN); if (column_values[0] == NULL) { ERROR ("dbi plugin: calloc failed."); BAIL_OUT (-1); } for (i = 1; i < column_num; i++) column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN; /* }}} */ /* Copy the field names to `column_names' */ for (i = 0; i < column_num; i++) /* {{{ */ { const char *column_name; column_name = dbi_result_get_field_name (res, (unsigned int) (i + 1)); if (column_name == NULL) { ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): " "Cannot retrieve name of field %zu.", db->name, udb_query_get_name (q), i + 1); BAIL_OUT (-1); } sstrncpy (column_names[i], column_name, DATA_MAX_NAME_LEN); } /* }}} for (i = 0; i < column_num; i++) */ udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g), /* plugin = */ "dbi", db->name, column_names, column_num, /* interval = */ (db->interval > 0) ? db->interval : 0); /* 0 = error; 1 = success; */ status = dbi_result_first_row (res); /* {{{ */ if (status != 1) { char errbuf[1024]; ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): " "dbi_result_first_row failed: %s. Maybe the statement didn't " "return any rows?", db->name, udb_query_get_name (q), cdbi_strerror (db->connection, errbuf, sizeof (errbuf))); udb_query_finish_result (q, prep_area); BAIL_OUT (-1); } /* }}} */ /* Iterate over all rows and call `udb_query_handle_result' with each list of * values. */ while (42) /* {{{ */ { status = 0; /* Copy the value of the columns to `column_values' */ for (i = 0; i < column_num; i++) /* {{{ */ { status = cdbi_result_get_field (res, (unsigned int) (i + 1), column_values[i], DATA_MAX_NAME_LEN); if (status != 0) { ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): " "cdbi_result_get_field (%zu) failed.", db->name, udb_query_get_name (q), i + 1); status = -1; break; } } /* }}} for (i = 0; i < column_num; i++) */ /* If all values were copied successfully, call `udb_query_handle_result' * to dispatch the row to the daemon. */ if (status == 0) /* {{{ */ { status = udb_query_handle_result (q, prep_area, column_values); if (status != 0) { ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): " "udb_query_handle_result failed.", db->name, udb_query_get_name (q)); } } /* }}} */ /* Get the next row from the database. */ status = dbi_result_next_row (res); /* {{{ */ if (status != 1) { if (dbi_conn_error (db->connection, NULL) != 0) { char errbuf[1024]; WARNING ("dbi plugin: cdbi_read_database_query (%s, %s): " "dbi_result_next_row failed: %s.", db->name, udb_query_get_name (q), cdbi_strerror (db->connection, errbuf, sizeof (errbuf))); } break; } /* }}} */ } /* }}} while (42) */ /* Tell the db query interface that we're done with this query. */ udb_query_finish_result (q, prep_area); /* Clean up and return `status = 0' (success) */ BAIL_OUT (0); #undef BAIL_OUT } /* }}} int cdbi_read_database_query */
void do_db( struct configuration_data *config, char *dbstring) { int rc; int try; const char *error; dbi_result result; /** * a NULL dbstring? May happen when a R/W VFS function * hat 0 bytes to transfer. This data is not relevant * for statistics. */ if (dbstring == NULL) return; /** * Check if the connection is alive. We try ten times * to restore the connection if not */ for (try = 0; try < 10; try++) { rc = dbi_conn_ping( config->DBIconn ); if (rc == 1) { result = dbi_conn_query(config->DBIconn, dbstring); if (result == NULL) { dbi_conn_error(config->DBIconn,&error); syslog(LOG_DEBUG,"DBI ERROR: %s",error); rc = 0;} else break; } } if (rc == 0 ) { syslog(LOG_DEBUG, "ERROR: Database handling error!"); return; } dbi_result_free(result); } void cleanup_cache( TALLOC_CTX *ctx,struct configuration_data *config, struct cache_entry *entry) { char *dbstring; struct cache_entry *go = entry; struct cache_entry *backup; struct cache_entry *backup2 = NULL; struct cache_entry *down =NULL; // left go = go->left; while (go != NULL) { backup = go->left; dbstring = cache_create_database_string(ctx,go,config); do_db(config,dbstring); talloc_free(dbstring); // go down down = go->down; while (down != NULL) { backup2 = down->down; dbstring = cache_create_database_string(ctx,down,config); do_db(config,dbstring); talloc_free(dbstring); talloc_free(down); down = backup2; } talloc_free(go); go = backup; } // right go = entry->right; while (go != NULL) { backup = go->right; dbstring = cache_create_database_string(ctx,go,config); do_db(config,dbstring); talloc_free(dbstring); // go down down = go->down; while (down != NULL) { backup2 = down->down; dbstring = cache_create_database_string(ctx,down,config); do_db(config,dbstring); talloc_free(dbstring); talloc_free(down); down = backup2; } talloc_free(go); go = backup; } // other_ops go = entry->other_ops; while (go != NULL) { backup = go->other_ops; dbstring = cache_create_database_string(ctx,go,config); do_db(config,dbstring); talloc_free(dbstring); talloc_free(go); go = backup; } // delete tree begin dbstring = cache_create_database_string(ctx,entry,config); do_db(config,dbstring); if (dbstring != NULL) talloc_free(dbstring); talloc_free(entry); } /* * cache_manager runs as a detached thread. Every half second, * it's checking if there's data available to store to the DB. * in case of yes, it walks through the list of data, enables * a new cache, and stores the data in the DB */ void cache_manager(struct configuration_data *config ) { int maintenance_c_val; if (config->precision>0) maintenance_c_val = config->maintenance_seconds / config->precision; else maintenance_c_val = config->maintenance_seconds; int maintenance_count = 0; pthread_detach(pthread_self()); /* backup the start and make it possible to * allocate a new cache beginning */ while (1 == 1) { if (config->precision != 0) sleep(config->precision); else sleep(5); maintenance_count++; pthread_mutex_lock(&cache_mutex); struct cache_entry *backup = cache_start; TALLOC_CTX *dbpool = talloc_pool(NULL,2048); cache_start = NULL; cache_end = NULL; pthread_mutex_unlock(&cache_mutex); if (backup != NULL) { /* store all existing entries into the database */ do_db(config,"BEGIN TRANSACTION;"); cleanup_cache( dbpool,config,backup); do_db(config,"COMMIT;"); } talloc_free(dbpool); if (maintenance_count == maintenance_c_val) { char String[400]; char dbstring[300]; struct tm *tm; do_db(config,"BEGIN TRANSACTION;"); time_t today=time(NULL); time_t delete_date=today - config->maint_run_time; tm = localtime ( &delete_date ); sprintf(String,"%04d-%02d-%02d %02d:%02d:%02d", \ tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, \ tm->tm_hour, tm->tm_min, tm->tm_sec); strcpy(dbstring,"delete from data where timestamp < '"); strcat(dbstring,String); strcat(dbstring,"';"); do_db(config,dbstring); do_db(config,"COMMIT;"); maintenance_count = 0; } } }
dbi_result _db_rawquery(const char *file, int line, database *db, int log_dupes, char *qry) { dbi_result result; const char *errmsg; int tries = 0; if (debug > 4) { LOGRAW(LOG_DEBUG, qry); } if (!dbi_conn_ping(db->conn)) { if (db->conn) dbi_conn_close(db->conn); db->conn = dbi_conn_new(db->driver); if (db->conn == NULL) { perror(db->driver); exit(1); } dbi_conn_set_option(db->conn, "host", db->host); dbi_conn_set_option(db->conn, "port", db->port); dbi_conn_set_option(db->conn, "username", db->username); dbi_conn_set_option(db->conn, "password", db->password); dbi_conn_set_option(db->conn, "dbname", db->name); retry: if (++tries == 3) exit(1); if (dbi_conn_connect(db->conn) < 0) { dbi_conn_error(db->conn, &errmsg); _logsrce = file; _logline = line; _LOG(LOG_ERR, "%s connection failed to %s:%s:%s %s", db->driver, db->host, db->port, db->name, errmsg); sleep(3); goto retry; } { char versionstring[VERSIONSTRING_LENGTH]; dbi_driver driver; driver = dbi_conn_get_driver(db->conn); dbi_conn_get_engine_version_string(db->conn, versionstring); LOG(LOG_INFO, "using driver: %s, version %s, compiled %s", dbi_driver_get_filename(driver), dbi_driver_get_version(driver), dbi_driver_get_date_compiled(driver)); LOG(LOG_INFO, "connected to %s:%s:%s, server version %s", db->host, db->port, db->name, versionstring); } } if (debug > 2) { char *src, *dst, buf[4096]; for (dst = buf, src = qry; *src; src++, dst++) { if (*src == '%') *dst++ = '%'; *dst = *src; } *dst = 0; LOG(LOG_INFO, buf); } result = dbi_conn_query(db->conn, qry); if (result == NULL) { int ret = dbi_conn_error(db->conn, &errmsg); _logsrce = file; _logline = line; _LOG(LOG_ERR, "query failed: %s (%s)", errmsg, qry); if (ret == DBI_ERROR_NOCONN) { dbi_conn_close(db->conn); db->conn = NULL; sleep(3); goto retry; } } return(result); }
/** * Prepare SQL queries and perform them. * * @param format printf-like string of SQL query * @param callback pointer to function to be called on results of SQL query * @param firstarg pointer to buffer for callback returned data * @return 0 (always, due to SQLite policy) */ int tagsistant_real_query( dbi_conn dbi, const char *format, int (*callback)(void *, dbi_result), char *file, int line, void *firstarg, ...) { va_list ap; va_start(ap, firstarg); /* check if connection has been created */ if (NULL == dbi) { dbg('s', LOG_ERR, "ERROR! DBI connection was not initialized!"); return(0); } #if TAGSISTANT_USE_QUERY_MUTEX /* lock the connection mutex */ g_mutex_lock(&tagsistant_query_mutex); #endif /* check if the connection is alive */ if (!dbi_conn_ping(dbi) && dbi_conn_connect(dbi) < 0) { #if TAGSISTANT_USE_QUERY_MUTEX g_mutex_unlock(&tagsistant_query_mutex); #endif dbg('s', LOG_ERR, "ERROR! DBI Connection has gone!"); return(0); } /* replace all the single or double quotes with "<><>" in the format */ gchar *escaped_format = g_regex_replace_literal(RX1, format, -1, 0, "<><>", 0, NULL); /* format the statement */ gchar *statement = g_strdup_vprintf(escaped_format, ap); if (NULL == statement) { #if TAGSISTANT_USE_QUERY_MUTEX /* lock the connection mutex */ g_mutex_unlock(&tagsistant_query_mutex); #endif dbg('s', LOG_ERR, "Null SQL statement"); g_free(escaped_format); return(0); } /* prepend a backslash to all the single quotes inside the arguments */ gchar *escaped_statement_tmp = g_regex_replace_literal(RX2, statement, -1, 0, "''", 0, NULL); /* replace "<><>" with a single quote */ gchar *escaped_statement = g_regex_replace_literal(RX3, escaped_statement_tmp, -1, 0, "'", 0, NULL); /* log and do the query */ dbg('s', LOG_INFO, "SQL from %s:%d: [%s]", file, line, escaped_statement); dbi_result result = dbi_conn_query(dbi, escaped_statement); tagsistant_dirty_logging(escaped_statement); tagsistant_wal(dbi, escaped_statement); g_free_null(escaped_format); g_free_null(escaped_statement_tmp); g_free_null(escaped_statement); /* call the callback function on results or report an error */ int rows = 0; if (result) { if (callback) { while (dbi_result_next_row(result)) { callback(firstarg, result); rows++; } } dbi_result_free(result); } else { /* get the error message */ const char *errmsg = NULL; dbi_conn_error(dbi, &errmsg); if (errmsg) dbg('s', LOG_ERR, "Error: %s.", errmsg); } #if TAGSISTANT_USE_QUERY_MUTEX g_mutex_unlock(&tagsistant_query_mutex); #endif return(rows); }
static int _sql_fetchrow(struct sql_table_helper* th,time_t *timestamp, rrd_value_t *value,int ordered) { char* dbi_errstr=NULL; char sql[10240]; time_t startt=0,endt=0; /*connect to the database if needed */ if (! th->conn) { rrd_set_error( "libdbi no parameters set for libdbi",th->filename,dbi_errstr); return -1; } if (! th->connected) { /* and now connect */ if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: connect to DB\n",time(NULL) ); } if (dbi_conn_connect(th->conn) <0) { dbi_conn_error(th->conn,(const char**)&dbi_errstr); rrd_set_error( "libdbi: problems connecting to db with connect string %s - error: %s",th->filename,dbi_errstr); _sql_close(th); return -1; } th->connected=1; } /* now find out regarding an existing result-set */ if (! th->result) { /* return if table_next is NULL */ if (th->table_next==NULL) { if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: reached last table to connect to\n",time(NULL) ); } /* but first close connection */ _sql_close(th); /* and return with end of data */ return 0; } /* calculate the table to use next */ th->table_start=th->table_next; th->table_next=_find_next_separator(th->table_start,'+'); _inline_unescape(th->table_start); /* and prepare FULL SQL Statement */ if (ordered) { snprintf(sql,sizeof(sql)-1,"SELECT %s as rrd_time, %s as rrd_value FROM %s WHERE %s ORDER BY %s", th->timestamp,th->value,th->table_start,th->where,th->timestamp); } else { snprintf(sql,sizeof(sql)-1,"SELECT %s as rrd_time, %s as rrd_value FROM %s WHERE %s", th->timestamp,th->value,th->table_start,th->where); } /* and execute sql */ if (getenv("RRDDEBUGSQL")) { startt=time(NULL); fprintf(stderr,"RRDDEBUGSQL: %li: executing %s\n",startt,sql); } th->result=dbi_conn_query(th->conn,sql); if (startt) { endt=time(NULL);fprintf(stderr,"RRDDEBUGSQL: %li: timing %li\n",endt,endt-startt); } /* handle error case */ if (! th->result) { dbi_conn_error(th->conn,(const char**)&dbi_errstr); if (startt) { fprintf(stderr,"RRDDEBUGSQL: %li: error %s\n",endt,dbi_errstr); } rrd_set_error("libdbi: problems with query: %s - errormessage: %s",sql,dbi_errstr); _sql_close(th); return -1; } } /* and now fetch key and value */ if (! dbi_result_next_row(th->result)) { /* free result */ dbi_result_free(th->result); th->result=NULL; /* and call recursively - this will open the next table or close connection as a whole*/ return _sql_fetchrow(th,timestamp,value,ordered); } /* and return with flag for one value */ *timestamp=rrd_fetch_dbi_long(th->result,1); *value=rrd_fetch_dbi_double(th->result,2); return 1; }
/** Users discovered a bug in some distributions of libdbi, where if * it is compiled on certain versions of gcc with the -ffast-math * compiler option it fails to correctly handle saving of 64-bit * values. This function tests for the problem. * @param: conn: The just-opened dbi_conn * @returns: GNC_DBI_PASS if the dbi library is safe to use, * GNC_DBI_FAIL_SETUP if the test could not be completed, or * GNC_DBI_FAIL_TEST if the bug was found. */ static GncDbiTestResult dbi_library_test (dbi_conn conn) { int64_t testlonglong = -9223372036854775807LL, resultlonglong = 0; uint64_t testulonglong = 9223372036854775807LLU, resultulonglong = 0; double testdouble = 1.7976921348623157E+307, resultdouble = 0.0; dbi_result result; GncDbiTestResult retval = GNC_DBI_PASS; result = dbi_conn_query (conn, "CREATE TEMPORARY TABLE numtest " "( test_int BIGINT, test_unsigned BIGINT," " test_double FLOAT8 )"); if (result == nullptr) { PWARN ("Test_DBI_Library: Create table failed"); return GNC_DBI_FAIL_SETUP; } dbi_result_free (result); std::stringstream querystr; querystr << "INSERT INTO numtest VALUES (" << testlonglong << ", " << testulonglong << ", " << std::setprecision(12) << testdouble << ")"; auto query = querystr.str(); result = dbi_conn_query (conn, query.c_str()); if (result == nullptr) { PWARN ("Test_DBI_Library: Failed to insert test row into table"); return GNC_DBI_FAIL_SETUP; } dbi_result_free (result); gnc_push_locale (LC_NUMERIC, "C"); result = dbi_conn_query (conn, "SELECT * FROM numtest"); if (result == nullptr) { const char* errmsg; dbi_conn_error (conn, &errmsg); PWARN ("Test_DBI_Library: Failed to retrieve test row into table: %s", errmsg); dbi_conn_query (conn, "DROP TABLE numtest"); gnc_pop_locale (LC_NUMERIC); return GNC_DBI_FAIL_SETUP; } while (dbi_result_next_row (result)) { resultlonglong = dbi_result_get_longlong (result, "test_int"); resultulonglong = dbi_result_get_ulonglong (result, "test_unsigned"); resultdouble = dbi_result_get_double (result, "test_double"); } gnc_pop_locale (LC_NUMERIC); if (testlonglong != resultlonglong) { PWARN ("Test_DBI_Library: LongLong Failed %" PRId64 " != % " PRId64, testlonglong, resultlonglong); retval = GNC_DBI_FAIL_TEST; } if (testulonglong != resultulonglong) { PWARN ("Test_DBI_Library: Unsigned longlong Failed %" PRIu64 " != %" PRIu64, testulonglong, resultulonglong); retval = GNC_DBI_FAIL_TEST; } /* A bug in libdbi stores only 7 digits of precision */ if (testdouble >= resultdouble + 0.000001e307 || testdouble <= resultdouble - 0.000001e307) { PWARN ("Test_DBI_Library: Double Failed %17e != %17e", testdouble, resultdouble); retval = GNC_DBI_FAIL_TEST; } return retval; }