Ejemplo n.º 1
0
Archivo: dbi.c Proyecto: Bradan/gammu
static void SMSDDBI_LogError(GSM_SMSDConfig * Config)
{
	int rc;
	const char *msg;
	rc = dbi_conn_error(Config->conn.dbi, &msg);
	if (rc == -1) {
		SMSD_Log(DEBUG_ERROR, Config, "Unknown DBI error!");
	} else {
		SMSD_Log(DEBUG_ERROR, Config, "DBI error %d: %s", rc, msg);
	}
}
Ejemplo n.º 2
0
// MySQL: 1062: Duplicate entry '1' for key 1
// PostgreSQL: ERROR:  duplicate key violates unique constraint ...
int dbi_duplicate_entry(dbi_conn conn)
{
    const char *errmsg;

    if (dbi_conn_error(conn, &errmsg) == DBI_ERROR_NONE) {
        return FALSE;
    }
    if (strcasestr(errmsg, "duplicate")) {
        return TRUE;
    }
    return FALSE;
}
Ejemplo n.º 3
0
template <> void
error_handler<DbType::DBI_MYSQL> (dbi_conn conn, void* user_data)
{
    GncDbiBackend<DbType::DBI_MYSQL>* dbi_be =
        static_cast<decltype(dbi_be)>(user_data);
    const char* msg;

    auto err_num = dbi_conn_error (conn, &msg);

    /* Note: the sql connection may not have been initialized yet
     *       so let's be careful with using it
     */

    /* Database doesn't exist. When this error is triggered the
     * GncDbiSqlConnection may not exist yet either, so don't use it here
     */
    if (err_num == 1049)            // Database doesn't exist
    {
        PINFO ("DBI error: %s\n", msg);
        dbi_be->set_exists(false);
        return;
    }

    /* All the other error handling code assumes the GncDbiSqlConnection
     *  has been initialized. So let's assert it exits here, otherwise
     * simply return.
     */
    if (!dbi_be->connected())
    {
        PINFO ("DBI error: %s\n", msg);
        PINFO ("Note: GbcDbiSqlConnection not yet initialized. Skipping further error processing.");
        return;
    }

    /* Test for other errors */
    if (err_num == 2006)       // Server has gone away
    {
        PINFO ("DBI error: %s - Reconnecting...\n", msg);
        dbi_be->set_dbi_error (ERR_BACKEND_CONN_LOST, 1, true);
        dbi_be->retry_connection(msg);
    }
    else if (err_num == 2003)       // Unable to connect
    {
        dbi_be->set_dbi_error (ERR_BACKEND_CANT_CONNECT, 1, true);
        dbi_be->retry_connection (msg);
    }
    else                            // Any other error
    {
        PERR ("DBI error: %s\n", msg);
        dbi_be->set_dbi_error (ERR_BACKEND_MISC, 0, FALSE);
    }
}
Ejemplo n.º 4
0
/**
	@brief Load a stored query.
	@param state Pointer to the query-building context.
	@param query_id ID of the query in query.stored_query.
	@return A pointer to the newly loaded StoredQ if successful, or NULL if not.

	The calling code is responsible for freeing the StoredQ by calling storedQFree().
*/
StoredQ* getStoredQuery( BuildSQLState* state, int query_id ) {
	if( !state )
		return NULL;

	// Check the stack to see if the current query is nested inside itself.  If it is, then
	// abort in order to avoid infinite recursion.  If it isn't, then add it to the stack.
	// (Make sure to pop it off the stack before returning.)
	if( searchIdStack( state->query_stack, query_id, NULL )) {
		osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
			"Infinite recursion detected; query # %d is nested within itself", query_id ));
		state->error = 1;
		return NULL;
	} else
		push_id( &state->query_stack, query_id, NULL );

	StoredQ* sq = NULL;
	dbi_result result = dbi_conn_queryf( state->dbhandle,
		"SELECT id, type, use_all, use_distinct, from_clause, where_clause, having_clause "
		"FROM query.stored_query WHERE id = %d;", query_id );
	if( result ) {
		if( dbi_result_first_row( result ) ) {
			sq = constructStoredQ( state, result );
			if( sq ) {
				PRINT( "Got a query row\n" );
				PRINT( "\tid: %d\n", sq->id );
				PRINT( "\ttype: %d\n", (int) sq->type );
				PRINT( "\tuse_all: %s\n", sq->use_all ? "true" : "false" );
				PRINT( "\tuse_distinct: %s\n", sq->use_distinct ? "true" : "false" );
			} else
				osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
					"Unable to build a query for id = %d", query_id ));
		} else {
			sqlAddMsg( state, "Stored query not found for id %d", query_id );
		}

		dbi_result_free( result );
	} else {
		const char* msg;
		int errnum = dbi_conn_error( state->dbhandle, &msg );
		osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state, 
			"Unable to query query.stored_query table: #%d %s",
			errnum, msg ? msg : "No description available" ));
	}

	pop_id( &state->query_stack );
	return sq;
}
Ejemplo n.º 5
0
/* Connect to the MYSQL database */
static logsql_opendb_ret log_sql_dbi_connect(server_rec *s, logsql_dbconnection *db)
{
    const char *driver = apr_table_get(db->parms,"driver");
	const char *host = apr_table_get(db->parms,"hostname");
	const char *user = apr_table_get(db->parms,"username");
	const char *passwd = apr_table_get(db->parms,"password");
	const char *database = apr_table_get(db->parms,"database");
	const char *s_tcpport = apr_table_get(db->parms,"port");
	unsigned int tcpport = (s_tcpport)?atoi(s_tcpport):0;
	const char *socketfile = apr_table_get(db->parms,"socketfile");
    //dbi_result result;
    dbi_conn_rec *dblink = db->handle;
    if (!dblink) {
        dblink = apr_pcalloc(db->p, sizeof(*dblink));
        db->handle = (void *)dblink;
    }

	dblink->conn = dbi_conn_new(driver);

    dbi_conn_set_option(dblink->conn, "host", host);
    dbi_conn_set_option(dblink->conn, "username", user);
    dbi_conn_set_option(dblink->conn, "password", passwd);
    dbi_conn_set_option(dblink->conn, "dbname", database);
    if (tcpport) {
        dbi_conn_set_option_numeric(dblink->conn, "port", tcpport);
    }

	if (socketfile && !strcmp(driver,"mysql")) {
		dbi_conn_set_option(dblink->conn, "mysql_unix_socket", socketfile);
	}
    
	if (!dbi_conn_connect(dblink->conn)) {
		log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
            "HOST: '%s' PORT: '%d' DB: '%s' USER: '******' SOCKET: '%s'",
			host, tcpport, database, user, socketfile);
		return LOGSQL_OPENDB_SUCCESS;
	} else {
        const char *error;
        dbi_conn_error(dblink->conn, &error);
		log_error(APLOG_MARK, APLOG_ERR, 0, s,
            "DBI Error: %s", error);
		log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
            "HOST: '%s' PORT: '%d' DB: '%s' USER: '******' SOCKET: '%s'",
			host, tcpport, database, user, socketfile);
		return LOGSQL_OPENDB_FAIL;
	}
}
Ejemplo n.º 6
0
static void
set_options(dbi_conn conn, const PairVec& options)
{
    for (auto option : options)
    {
        auto opt = option.first.c_str();
        auto val = option.second.c_str();
        auto result = dbi_conn_set_option(conn, opt, val);
        if (result < 0)
        {
            const char *msg = nullptr;
            int err = dbi_conn_error(conn, &msg);
            PERR("Error setting %s option to %s: %s", opt, val, msg);
            throw std::runtime_error(msg);
        }
    }
}
Ejemplo n.º 7
0
template<> void
error_handler<DbType::DBI_PGSQL> (dbi_conn conn, void* user_data)
{
    GncDbiBackend<DbType::DBI_PGSQL>* dbi_be =
        static_cast<decltype(dbi_be)>(user_data);
    const char* msg;

    (void)dbi_conn_error (conn, &msg);
    if (g_str_has_prefix (msg, "FATAL:  database") &&
        g_str_has_suffix (msg, "does not exist\n"))
    {
        PINFO ("DBI error: %s\n", msg);
        dbi_be->set_exists(false);
    }
    else if (g_strrstr (msg,
                        "server closed the connection unexpectedly"))    // Connection lost
    {
        if (!dbi_be->connected())
        {
            PWARN ("DBI Error: Connection lost, connection pointer invalid");
            return;
        }
        PINFO ("DBI error: %s - Reconnecting...\n", msg);
        dbi_be->set_dbi_error (ERR_BACKEND_CONN_LOST, 1, true);
        dbi_be->retry_connection(msg);
    }
    else if (g_str_has_prefix (msg, "connection pointer is NULL") ||
             g_str_has_prefix (msg, "could not connect to server"))       // No connection
    {

        if (!dbi_be->connected())
            qof_backend_set_error(reinterpret_cast<QofBackend*>(dbi_be),
                                  ERR_BACKEND_CANT_CONNECT);
        else
        {
            dbi_be->set_dbi_error(ERR_BACKEND_CANT_CONNECT, 1, true);
            dbi_be->retry_connection (msg);
        }
    }
    else
    {
        PERR ("DBI error: %s\n", msg);
        if (dbi_be->connected())
            dbi_be->set_dbi_error (ERR_BACKEND_MISC, 0, false);
    }
}
Ejemplo n.º 8
0
Archivo: dbi.c Proyecto: Bradan/gammu
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;
}
Ejemplo n.º 9
0
static SelectItem* getSelectList( BuildSQLState* state, int query_id ) {
	SelectItem* select_list = NULL;

	// The ORDER BY is in descending order so that we can build the list by adding to
	// the head, and it will wind up in the right order.
	dbi_result result = dbi_conn_queryf( state->dbhandle,
		"SELECT id, stored_query, seq_no, expression, column_alias, grouped_by "
		"FROM query.select_item WHERE stored_query = %d ORDER BY seq_no DESC", query_id );
	if( result ) {
		if( dbi_result_first_row( result ) ) {
			while( 1 ) {
				SelectItem* item = constructSelectItem( state, result );
				if( item ) {
					PRINT( "Found a SELECT item\n" );
					PRINT( "\tid: %d\n", item->id );
					PRINT( "\tstored_query_id: %d\n", item->stored_query_id );
					PRINT( "\tseq_no: %d\n", item->seq_no );
					PRINT( "\tcolumn_alias: %s\n",
							item->column_alias ? item->column_alias : "(none)" );
					PRINT( "\tgrouped_by: %d\n", item->grouped_by );

					item->next = select_list;
					select_list = item;
				} else {
					osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
						"Unable to build select list for query id #%d", query_id ));
					selectListFree( select_list );
					select_list = NULL;
					break;
				}
				if( !dbi_result_next_row( result ) )
					break;
			};
		}
	} else {
		const char* msg;
		int errnum = dbi_conn_error( state->dbhandle, &msg );
		osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
					  "Unable to query query.select_list table: #%d %s",
					  errnum, msg ? msg : "No description available" ));
	}

	return select_list;
}
Ejemplo n.º 10
0
/**
 * Safely resave a database by renaming all of its tables, recreating
 * everything, and then dropping the backup tables only if there were
 * no errors. If there are errors, drop the new tables and restore the
 * originals.
 *
 * @param qbe: QofBackend for the session.
 * @param book: QofBook to be saved in the database.
 */
void
gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
{
    GncDbiBackend* be = (GncDbiBackend*)qbe;
    auto conn = dynamic_cast<GncDbiSqlConnection*>(be->m_conn);

    g_return_if_fail (conn != nullptr);
    g_return_if_fail (be != nullptr);
    g_return_if_fail (book != nullptr);

    ENTER ("book=%p, primary=%p", book, be->m_book);
    auto table_list = conn->m_provider->get_table_list (conn->conn(), "");
    if (!conn->table_operation (table_list, backup))
    {
        qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
        conn->table_operation (table_list, rollback);
        LEAVE ("Failed to rename tables");
        return;
    }
    auto index_list = conn->m_provider->get_index_list (conn->m_conn);
    for (auto index : index_list)
    {
        const char* errmsg;
        conn->m_provider->drop_index (conn->m_conn, index);
        if (DBI_ERROR_NONE != dbi_conn_error (conn->m_conn, &errmsg))
        {
            qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
            conn->table_operation (table_list, rollback);
            LEAVE ("Failed to drop indexes %s", errmsg);
            return;
        }
    }

    gnc_sql_sync_all (be, book);
    if (qof_backend_check_error (qbe))
    {
        conn->table_operation (table_list, rollback);
        LEAVE ("Failed to create new database tables");
        return;
    }
    conn->table_operation (table_list, drop_backup);
    LEAVE ("book=%p", book);
}
Ejemplo n.º 11
0
static Expression* getExpression( BuildSQLState* state, int id ) {
	
	// Check the stack to see if the current expression is nested inside itself.  If it is,
	// then abort in order to avoid infinite recursion.  If it isn't, then add it to the
	// stack.  (Make sure to pop it off the stack before returning.)
	if( searchIdStack( state->expr_stack, id, NULL )) {
		osrfLogWarning( OSRF_LOG_MARK, sqlAddMsg( state,
			"Infinite recursion detected; expression # %d is nested within itself", id ));
		state->error = 1;
		return NULL;
	} else
		push_id( &state->expr_stack, id, NULL );

		Expression* exp = NULL;
	dbi_result result = dbi_conn_queryf( state->dbhandle,
		"SELECT id, type, parenthesize, parent_expr, seq_no, literal, table_alias, "
		"column_name, left_operand, operator, right_operand, function_id, subquery, cast_type "
		"FROM query.expression WHERE id = %d;", id );
	if( result ) {
		if( dbi_result_first_row( result ) ) {
			exp = constructExpression( state, result );
			if( exp ) {
				PRINT( "Got an expression\n" );
				PRINT( "\tid = %d\n", exp->id );
				PRINT( "\ttype = %d\n", exp->type );
				PRINT( "\tparenthesize = %d\n", exp->parenthesize );
				PRINT( "\tcolumn_name = %s\n", exp->column_name ? exp->column_name : "(none)" );
			} else 
				osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
					"Unable to construct an Expression for id = %d", id ));
		}
	} else {
		const char* msg;
		int errnum = dbi_conn_error( state->dbhandle, &msg );
		osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
			"Unable to query query.expression table: #%d %s",
			errnum, msg ? msg : "No description available" ));
	}

	pop_id( &state->expr_stack );
	return exp;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
/**
	@brief Build a list of joined relations.
	@param state Pointer to the query-building context.
	@param id ID of the parent relation.
	@return A pointer to the first in a linked list of FromRelations, if there are any; or
		NULL if there aren't any, or in case of an error.

	Look for relations joined directly to the parent relation, and make a list of them.
*/
static FromRelation* getJoinList( BuildSQLState* state, int id ) {
	FromRelation* join_list = NULL;
	
	// The ORDER BY is in descending order so that we can build the list by adding to
	// the head, and it will wind up in the right order.
	dbi_result result = dbi_conn_queryf( state->dbhandle,
		"SELECT id, type, table_name, class_name, subquery, function_call, "
		"table_alias, parent_relation, seq_no, join_type, on_clause "
		"FROM query.from_relation WHERE parent_relation = %d ORDER BY seq_no DESC", id );

	if( result ) {
		if( dbi_result_first_row( result ) ) {
			while( 1 ) {
				FromRelation* relation = constructFromRelation( state, result );
				if( relation ) {
					PRINT( "Found a joined relation\n" );
					PRINT( "\tjoin_type: %d\n", relation->join_type );
					PRINT( "\ttable_name: %s\n", relation->table_name );
					relation->next = join_list;
					join_list = relation;
				} else {
					osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
						"Unable to build join list for from relation id #%d", id ));
					joinListFree( join_list );
					join_list = NULL;
					break;
				}
				if( !dbi_result_next_row( result ) )
					break;
			};
		}
	} else {
		const char* msg;
		int errnum = dbi_conn_error( state->dbhandle, &msg );
		osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
			"Unable to query query.from_relation table for join list: #%d %s",
			errnum, msg ? msg : "No description available" ));
	}

	return join_list;
}
Ejemplo n.º 14
0
static int _sql_setparam(struct sql_table_helper* th,char* key, char* value) {
  char* dbi_errstr=NULL;
  dbi_driver driver;
  /* if not connected */
  if (! th->conn) {
    /* initialize some stuff */
    th->table_next=th->table_start;
    th->result=NULL;
    th->connected=0;
    /* initialize db */
    if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: initialize libDBI\n",time(NULL) ); }
    dbi_initialize(NULL);
    /* load the driver */
    driver=dbi_driver_open(th->dbdriver);
    if (! driver) {
      rrd_set_error( "libdbi - no such driver: %s (possibly a dynamic link problem of the driver being linked without -ldbi)",th->dbdriver); 
      return -1; 
    }
    /* and connect to driver */
    th->conn=dbi_conn_open(driver);
    /* and handle errors */
    if (! th->conn) { 
      rrd_set_error( "libdbi - could not open connection to driver %s",th->dbdriver); 
      dbi_shutdown();
      return -1;
    }
  }
  if (th->connected) {
    rrd_set_error( "we are already connected - can not set parameter %s=%s",key,value);
    _sql_close(th);
    return -1; 
  }
  if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: setting option %s to %s\n",time(NULL),key,value ); }
  if (dbi_conn_set_option(th->conn,key,value)) {
    dbi_conn_error(th->conn,(const char**)&dbi_errstr);
    rrd_set_error( "libdbi: problems setting %s to %s - %s",key,value,dbi_errstr);
    _sql_close(th);
    return -1;
  }
  return 0;
}
Ejemplo n.º 15
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;
}
Ejemplo n.º 16
0
ENDfreeInstance


BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
	/* nothing special here */
ENDdbgPrintInstInfo


/* log a database error with descriptive message.
 * We check if we have a valid database handle. If not, we simply
 * report an error, but can not be specific. RGerhards, 2007-01-30
 */
static void
reportDBError(instanceData *pData, int bSilent)
{
	unsigned uDBErrno;
	char errMsg[1024];
	const char *pszDbiErr;

	BEGINfunc
	ASSERT(pData != NULL);

	/* output log message */
	errno = 0;
	if(pData->conn == NULL) {
		errmsg.LogError(0, NO_ERRCODE, "unknown DB error occured - could not obtain connection handle");
	} else { /* we can ask dbi for the error description... */
		uDBErrno = dbi_conn_error(pData->conn, &pszDbiErr);
		snprintf(errMsg, sizeof(errMsg)/sizeof(char), "db error (%d): %s\n", uDBErrno, pszDbiErr);
		if(bSilent || uDBErrno == pData->uLastDBErrno)
			dbgprintf("libdbi, DBError(silent): %s\n", errMsg);
		else {
			pData->uLastDBErrno = uDBErrno;
			errmsg.LogError(0, NO_ERRCODE, "%s", errMsg);
		}
	}
		
	ENDfunc
}
Ejemplo n.º 17
0
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");
}
Ejemplo n.º 18
0
/*
 * Functions
 */
static const char *cdbi_strerror (dbi_conn conn, /* {{{ */
    char *buffer, size_t buffer_size)
{
  const char *msg;
  int status;

  if (conn == NULL)
  {
    sstrncpy (buffer, "connection is NULL", buffer_size);
    return (buffer);
  }

  msg = NULL;
  status = dbi_conn_error (conn, &msg);
  if ((status >= 0) && (msg != NULL))
    ssnprintf (buffer, buffer_size, "%s (status %i)", msg, status);
  else
    ssnprintf (buffer, buffer_size, "dbi_conn_error failed with status %i",
        status);

  return (buffer);
} /* }}} const char *cdbi_conn_error */
Ejemplo n.º 19
0
static OrderItem* getOrderByList( BuildSQLState* state, int query_id ) {
	OrderItem* ord_list = NULL;

	// The ORDER BY is in descending order so that we can build the list by adding to
	// the head, and it will wind up in the right order.
	dbi_result result = dbi_conn_queryf( state->dbhandle,
		"SELECT id, stored_query, seq_no, expression "
		"FROM query.order_by_item WHERE stored_query = %d ORDER BY seq_no DESC", query_id );
	if( result ) {
		if( dbi_result_first_row( result ) ) {
			while( 1 ) {
				OrderItem* item = constructOrderItem( state, result );
				if( item ) {
					PRINT( "Found an ORDER BY item\n" );

					item->next = ord_list;
					ord_list = item;
				} else {
					osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
						"Unable to build ORDER BY item for query id #%d", query_id ));
					orderItemListFree( ord_list );
					ord_list = NULL;
					break;
				}
				if( !dbi_result_next_row( result ) )
					break;
			};
		}
	}  else {
		const char* msg;
		int errnum = dbi_conn_error( state->dbhandle, &msg );
		osrfLogError( OSRF_LOG_MARK, sqlAddMsg( state,
			"Unable to query query.order_by_list table: #%d %s",
			errnum, msg ? msg : "No description available" ));
	}

	return ord_list;
}
Ejemplo n.º 20
0
//*******************************************************************
// STORE RAW RESULTS
//*******************************************************************
static gint mysqlstats_store_raw_result(trx *t)
{
  dbi_result result;
  struct mysqlstats_result *res = (struct mysqlstats_result *)t->res;
  struct probe_def *def = (struct probe_def *)t->def;
  char *escmsg;
  const char *errmsg;

  if (t->res->color == STAT_PURPLE) return 1;
  t->seen_before = FALSE;
  if (res->message) {
    dbi_conn_quote_string_copy(t->probe->db->conn, t->res->message, &escmsg);
  } else {
    escmsg = strdup("");
  }
    
  result = db_query(t->probe->db, 0,
                    "insert into pr_mysqlstats_raw (probe, yellow, red, stattime, color, selectq, insertq, "
                    "                               updateq, deleteq, message) "
                    "            values ('%u', '%f', '%f', '%u', '%u', '%u', '%u', "
                    "                    '%u', '%u', '%s')",
                    def->probeid, def->yellow, def->red, res->stattime, res->color, 
                    res->selectq, res->insertq, res->updateq, res->deleteq,escmsg);
  g_free(escmsg);
  if (result) {
    dbi_result_free(result);
    return 1; // success
  }
  if (dbi_duplicate_entry(t->probe->db->conn)) {
    t->seen_before = TRUE;
    return 1; // success
  }
  if (dbi_conn_error(t->probe->db->conn, &errmsg) == DBI_ERROR_NONE) {
    return 1; // success
  }
  LOG(LOG_ERR, "%s", errmsg);
  return 0; // Failure
}
Ejemplo n.º 21
0
static inline gboolean
afsql_dd_handle_insert_row_error_depending_on_connection_availability(AFSqlDestDriver *self,
                                                                      LogMessage *msg,
                                                                      LogPathOptions *path_options)
{
  const gchar *dbi_error, *error_message;

  if (dbi_conn_ping(self->dbi_ctx) == 1)
    {
      log_queue_push_head(self->queue, msg, path_options);
      return TRUE;
    }

  if (afsql_dd_is_transaction_handling_enabled(self))
    {
      error_message = "SQL connection lost in the middle of a transaction,"
                      " rewinding backlog and starting again";
      afsql_dd_handle_transaction_error(self);
    }
  else
    {
      error_message = "Error, no SQL connection after failed query attempt";
      log_queue_push_head(self->queue, msg, path_options);
    }

  dbi_conn_error(self->dbi_ctx, &dbi_error);
  msg_error(error_message,
            evt_tag_str("type", self->type),
            evt_tag_str("host", self->host),
            evt_tag_str("port", self->port),
            evt_tag_str("username", self->user),
            evt_tag_str("database", self->database),
            evt_tag_str("error", dbi_error),
            NULL);

  return FALSE;
}
Ejemplo n.º 22
0
static gboolean
afsql_dd_insert_fail_handler(AFSqlDestDriver *self, LogMessage *msg,
                             LogPathOptions *path_options)
{
  if (self->failed_message_counter < self->num_retries - 1)
    {
      log_queue_push_head(self->queue, msg, path_options);

      /* database connection status sanity check after failed query */
      if (dbi_conn_ping(self->dbi_ctx) != 1)
        {
          const gchar *dbi_error;

          dbi_conn_error(self->dbi_ctx, &dbi_error);
          msg_error("Error, no SQL connection after failed query attempt",
                    evt_tag_str("type", self->type),
                    evt_tag_str("host", self->host),
                    evt_tag_str("port", self->port),
                    evt_tag_str("username", self->user),
                    evt_tag_str("database", self->database),
                    evt_tag_str("error", dbi_error),
                    NULL);
          return FALSE;
        }

      self->failed_message_counter++;
      return FALSE;
    }

  msg_error("Multiple failures while inserting this record into the database, message dropped",
            evt_tag_int("attempts", self->num_retries),
            NULL);
  stats_counter_inc(self->dropped_messages);
  log_msg_drop(msg, path_options);
  self->failed_message_counter = 0;
  return TRUE;
}
Ejemplo n.º 23
0
dbi_conn open_database(const char *dbtype, const char *dbhost, const char *dbport, const char *dbname, const char *dbuser, const char *dbpasswd)
{
  dbi_conn conn;

  dbi_initialize(NULL);
  conn = dbi_conn_new(dbtype);
  if ( ! conn ) { LOG(LOG_ERR, "Cannot start a connection with driver %s", dbtype); }

  dbi_conn_set_option(conn, "host", dbhost);
  dbi_conn_set_option(conn, "port", dbport);
  dbi_conn_set_option(conn, "username", dbuser);
  dbi_conn_set_option(conn, "password", dbpasswd);
  dbi_conn_set_option(conn, "dbname", dbname);
  dbi_conn_set_option(conn, "encoding", "UTF-8");

  if (dbi_conn_connect(conn) < 0) {
    const char *errmsg;
    dbi_conn_error(conn, &errmsg);
    LOG(LOG_ERR, "%s dbhost=%s,dbport=%d,dbname=%s,dbuser=%s,dbpasswd=%s",
           errmsg, dbhost, dbport, dbname, dbuser, dbpasswd);
    return(NULL);
  }
  return(conn);
}
Ejemplo n.º 24
0
//*******************************************************************
// STORE RAW RESULTS
//*******************************************************************
static gint bb_cpu_store_raw_result(trx *t)
{
  dbi_result result;
  struct bb_cpu_result *res = (struct bb_cpu_result *)t->res;
  struct probe_def *def = (struct probe_def *)t->def;
  char *escmsg;
  const char *errmsg;

  if (t->res->color == STAT_PURPLE) return 1;
  t->seen_before = FALSE;
  if (res->message) {
    dbi_conn_quote_string_copy(t->probe->db->conn, t->res->message, &escmsg);
  } else {
    escmsg = strdup("");
  }
    
  result = db_query(t->probe->db, 0,
                    "insert into pr_bb_cpu_raw (probe, stattime, color, loadavg, user, idle, free, used, message)"
                    "            values ('%u', '%u', '%u', '%f', '%u',  '%u', '%u', '%u', '%s')",
                    def->probeid, res->stattime, res->color, res->loadavg,
                    res->user, res->idle, res->free, res->used, escmsg);
  g_free(escmsg);
  if (result) {
    dbi_result_free(result);
    return 1; // success
  }
  if (dbi_duplicate_entry(t->probe->db->conn)) {
    t->seen_before = TRUE;
    return 1; // success
  }
  if (dbi_conn_error(t->probe->db->conn, &errmsg) == DBI_ERROR_NONE) {
    return 1; // success
  }
  LOG(LOG_ERR, "%s", errmsg);
  return 0; // Failure
}
Ejemplo n.º 25
0
void refresh_database(dbi_conn conn)
{
  dbi_result result;
  char qry[1024];

  sprintf(qry,  "SELECT pr_mysql_def.id, pr_mysql_def.domid, pr_mysql_def.tblid, pr_realm.name, "
                "       pr_mysql_def.ipaddress, pr_mysql_def.dbname, "
                "       pr_mysql_def.dbuser, pr_mysql_def.dbpasswd,"
                "       pr_mysql_def.query, "
                "       pr_mysql_def.yellow,  pr_mysql_def.red "
                "FROM   pr_mysql_def, pr_realm "
                "WHERE  pr_mysql_def.id > 1 and pr_mysql_def.disable <> 'yes'"
                "       and pr_mysql_def.pgroup = '%d' and pr_realm.id = pr_mysql_def.domid",
                (unsigned)OPT_VALUE_GROUPID);

  result = db_query(conn, 1, qry);
  if (!result) {
    return;
  }
    
  while (dbi_result_next_row(result)) {
    int id;
    struct probedef *probe;

    id = dbi_result_get_uint(result, "id");
    probe = g_hash_table_lookup(cache, &id);
    if (!probe) {
      probe = g_malloc0(sizeof(struct probedef));
      if (dbi_result_get_uint(result, "domid") > 1) {
        probe->probeid = dbi_result_get_uint(result, "tblid");
        probe->realm=strdup(dbi_result_get_string(result, "name"));
      } else {
        probe->probeid = probe->id;
      }
      g_hash_table_insert(cache, guintdup(id), probe);
    }

    if (probe->ipaddress) g_free(probe->ipaddress);
    probe->ipaddress = dbi_result_get_string_copy(result, "ipaddress");
    if (probe->dbname) g_free(probe->dbname);
    probe->dbname = dbi_result_get_string_copy(result, "dbname");
    if (probe->dbuser) g_free(probe->dbuser);
    probe->dbuser = dbi_result_get_string_copy(result, "dbuser");
    if (probe->dbpasswd) g_free(probe->dbpasswd);
    probe->dbpasswd = dbi_result_get_string_copy(result, "dbpasswd");
    if (probe->query) g_free(probe->query);
    probe->query = dbi_result_get_string_copy(result, "query");
    probe->yellow = dbi_result_get_float(result, "yellow");
    probe->red = dbi_result_get_float(result, "red");
    if (probe->msg) g_free(probe->msg);
    probe->msg = NULL;
    probe->seen = 1;
  }
  if (dbi_conn_error_flag(conn)) {
    const char *errmsg;
    dbi_conn_error(conn, &errmsg);
    LOG(LOG_ERR, "%s", errmsg);
    g_hash_table_foreach(cache, reset_seen, NULL);
  } else {
    g_hash_table_foreach_remove(cache, return_seen, NULL);
  }
  dbi_result_free(result);
}
Ejemplo n.º 26
0
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 */
Ejemplo n.º 27
0
static gboolean
afsql_dd_ensure_initialized_connection(AFSqlDestDriver *self)
{
  if (self->dbi_ctx)
    return TRUE;

  self->dbi_ctx = dbi_conn_new(self->type);

  if (!self->dbi_ctx)
    {
      msg_error("No such DBI driver",
                evt_tag_str("type", self->type),
                NULL);
      return FALSE;
    }

  dbi_conn_set_option(self->dbi_ctx, "host", self->host);

  if (strcmp(self->type, "mysql"))
    dbi_conn_set_option(self->dbi_ctx, "port", self->port);
  else
    dbi_conn_set_option_numeric(self->dbi_ctx, "port", atoi(self->port));

  dbi_conn_set_option(self->dbi_ctx, "username", self->user);
  dbi_conn_set_option(self->dbi_ctx, "password", self->password);
  dbi_conn_set_option(self->dbi_ctx, "dbname", self->database);
  dbi_conn_set_option(self->dbi_ctx, "encoding", self->encoding);
  dbi_conn_set_option(self->dbi_ctx, "auto-commit", self->flags & AFSQL_DDF_EXPLICIT_COMMITS ? "false" : "true");

  /* database specific hacks */
  dbi_conn_set_option(self->dbi_ctx, "sqlite_dbdir", "");
  dbi_conn_set_option(self->dbi_ctx, "sqlite3_dbdir", "");

  /* Set user-specified options */
  g_hash_table_foreach(self->dbd_options, afsql_dd_set_dbd_opt, self->dbi_ctx);
  g_hash_table_foreach(self->dbd_options_numeric, afsql_dd_set_dbd_opt_numeric, self->dbi_ctx);

  if (dbi_conn_connect(self->dbi_ctx) < 0)
    {
      const gchar *dbi_error;

      dbi_conn_error(self->dbi_ctx, &dbi_error);

      msg_error("Error establishing SQL connection",
                evt_tag_str("type", self->type),
                evt_tag_str("host", self->host),
                evt_tag_str("port", self->port),
                evt_tag_str("username", self->user),
                evt_tag_str("database", self->database),
                evt_tag_str("error", dbi_error),
                NULL);

      return FALSE;
    }

  if (self->session_statements != NULL)
    {
      GList *l;

      for (l = self->session_statements; l; l = l->next)
        {
          if (!afsql_dd_run_query(self, (gchar *) l->data, FALSE, NULL))
            {
              msg_error("Error executing SQL connection statement",
                        evt_tag_str("statement", (gchar *) l->data),
                        NULL);

              return FALSE;
            }
        }
    }

  return TRUE;
}
Ejemplo n.º 28
0
 int dberror() const noexcept override {
     return dbi_conn_error(m_conn, nullptr);
 }
Ejemplo n.º 29
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);
}
Ejemplo n.º 30
0
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;
}