///////
   //    Simple Interface class for a MySQL client application
   //    
   //    Copyright (c) 1999-2004 Comune di Prato - Prato - Italy
   //    Some Portions Copyright (c) 2008 Devise.IT srl <http://www.devise.it/>
   //    Author: Gabriele Bartolini - Prato - Italy <angusgb@users.sourceforge.net>
   //
   //    For copyright details, see the file COPYING in your distribution
   //    or the GNU General Public License version 2 or later 
   //    <http://www.gnu.org/copyleft/gpl.html>
   //
   //    G. Bartolini - started: June 1999
   //
   //    $Id: Htmysql.cc,v 1.14 2009/08/26 12:25:57 angusgb Exp $
   //
///////


#ifdef HAVE_CONFIG_H
#include "htconfig.h"
#endif /* HAVE_CONFIG_H */

#ifdef HAVE_STD
#include <iostream>
#ifdef HAVE_NAMESPACES
using namespace std;
#endif
#else
#include <iostream.h>
#endif /* HAVE_STD */

#include "Htmysql.h"

   // Static variables initialization
      int Htmysql::debug = 0;

// Constructor

Htmysql::Htmysql()
: drop_database(true)
{
   Init();  // Initialization
}

// Destructor

Htmysql::~Htmysql()
{
   Close(); // Close the connection
}

// Initialize the space for managing the mysql Database instance
int Htmysql::Init ()
{
   if (! ::mysql_init (&mysql)) return 0; // memory allocation failed
   else return 1;
}

// Returns the last generated ID
int Htmysql::GetLastID ()
{
   return mysql_insert_id (&mysql);
}


// Connect to a mysql server
int Htmysql::Connect (const char *host, const char *user, const char *passwd,
                        const char *db, uint port, const char *unix_socket,
                        uint client_flag)
{

   MYSQL* rv (::mysql_real_connect ( &mysql, (host?host:"localhost"),
	 user, passwd, db,
	 port, unix_socket, client_flag));

   if (rv == &mysql)
       return 1;

   return 0;
}


// Close the connection
void Htmysql::Close ()
{
   return ::mysql_close(&mysql);
}

void Htmysql::ReadDefaultGroup(const std::string& group)
{
	::mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, group.c_str());
}

// Ping and checks for the connection
int Htmysql::Ping ()
{
   return ::mysql_ping (&mysql);
}

// Retrieve the error number
int Htmysql::GetError()
{
   return mysql_errno (&mysql);
}


// Display an error message, depending on mysql_errno value
int Htmysql::DisplayError(ostream & _stream)
{
   _stream << "Error (" << GetError() <<
   	       	   "): " << mysql_error(&mysql) << endl;
   
   return mysql_errno (&mysql);
}


// Execute a query
int Htmysql::SelectDB(const std::string db)
{
   return ::mysql_select_db (&mysql, db.c_str());
}


// Execute a query
int Htmysql::ExecQuery(const std::string query)
{
   return ::mysql_query (&mysql, query.c_str());
}


// Stores the results of the last query executed

HtmysqlQueryResult *Htmysql::StoreResult()
{
   
   HtmysqlQueryResult * Result = new HtmysqlQueryResult;

   if (Result)
   	 Result = StoreResult (* Result);
      
   return Result;
   
}


// Stores the results of the last query executed, given a QueryResult

HtmysqlQueryResult *Htmysql::StoreResult(HtmysqlQueryResult &Result)
{
   
   Result.Set(::mysql_store_result (&mysql));

   Result._query_type = Htmysql_Stored;
   
   return &Result;
   
}


// Get the next element from the connection (directly) without storing
// it in a temporary table.

HtmysqlQueryResult *Htmysql::UseResult(HtmysqlQueryResult &Result)
{
   
   Result.Set(::mysql_use_result (&mysql));

   Result._query_type = Htmysql_Temporary;
   
   return &Result;
   
}

HtmysqlQueryResult *Htmysql::UseResult()
{
   
   HtmysqlQueryResult * Result = new HtmysqlQueryResult;

   if (Result)
   	 Result = UseResult (* Result);
      
   return Result;
   
}


// Retrieve the list of database, by specifying a pattern

HtmysqlQueryResult *Htmysql::ListDBs(const char *wild)
{

   MYSQL_RES *tmp;
   
   if (! (tmp = mysql_list_dbs (&mysql, wild)))
      return NULL;   // Failed to obtain the list
   
   HtmysqlQueryResult *Result = new HtmysqlQueryResult;
   
   if (Result)
      Result->Set(tmp); // Set the result of the database listing
   
   return Result;
   
}


// Does a db exist?

int Htmysql::Exists(const std::string &dbname)
{
   int returnvalue;
   
   HtmysqlQueryResult *tmp;
   
   if ( ! (tmp = ListDBs (dbname.c_str()) )) returnvalue = -1;
   else returnvalue = tmp->rows;
   
   delete (tmp);
   
   return returnvalue;
}



///////
   //    HtmysqlQueryResult class definition
///////

// Constructor

HtmysqlQueryResult::HtmysqlQueryResult()
{
   result=0;
   rows=0;
   fields=0;
   _query_type=Htmysql::Htmysql_Stored;   // Default query type
}

// Destructor

HtmysqlQueryResult::~HtmysqlQueryResult()
{
   if (result) Free();
}


// Set the query result member

void HtmysqlQueryResult::Set(MYSQL_RES *res)
{
   // Discard and free any previous result
   if (result) Free();   
   result=res;
   
   Refresh();
}


// Free the memory

void HtmysqlQueryResult::Free()
{
   ::mysql_free_result(result);
   
   result = 0;
   
}


// Refresh the number of fields and rows

void HtmysqlQueryResult::Refresh()
{
   if (result)
   {

      if (_query_type == Htmysql::Htmysql_Stored)
         rows = mysql_num_rows (result);
      else rows = 1;
      fields = mysql_num_fields (result);
   }
   else
   {
      rows = 0;
      fields = 0;
   }
}


MYSQL_ROW HtmysqlQueryResult::GetNextRecord()
{
   if (! result) return NULL;
   
   _record = mysql_fetch_row (result);

   return _record;
   
}


// View the whole database (fields and rows)

void HtmysqlQueryResult::View (ostream & _stream)
{

   register unsigned int i;

   while (GetNextRecord())
   {
      for (i=0; i < fields; i++)
      {
         _stream << "[" << (_record[i] ? _record[i]: "NULL") << "] ";
      }
		  
      _stream << endl;
   }
   
}
