/**
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 * In particular this file is part of the iWear Database Access Library.
 *
 * The iWear Framework 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 as in version 2 of the License.
 * 
 * The iWear Framework 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
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __IWEAR_DB_DB_H
#define __IWEAR_DB_DB_H

#include "iwear/iwear.h"
#include "iwear/db/config.h"
#include "iwear/db/recordset.h"
#include "iwear/cstdint.h"

namespace iwear {
    namespace db {

class transaction_implementation;

class transaction
{
    transaction_implementation* timpl;
    transaction( const transaction& ) { }
    transaction& operator=( const transaction& ) { return *this; }
public:
    transaction( transaction_implementation& ti );

    ~transaction( );

    void commit( void );
    void rollback( void );

    record_set query( const std::string& q );

    /**
     * @note Read carefully what your implementation supports.
     */
    enum isolation_level
    {
	read_committed,
	read_uncommitted,
	repeatable_read,
	serializable
    };

};

class transaction_implementation
{
protected:
    friend class transaction;
    virtual void transact( void ) = 0;
    virtual void commit( void ) = 0;
    virtual void rollback( void ) = 0;

    virtual record_set_implementation& query( const std::string& ) = 0;
    virtual ~transaction_implementation() { }
};

inline
transaction::transaction( transaction_implementation& ti ) : timpl(&ti)
{
    timpl->transact();
}

inline
transaction::~transaction( )
{
    delete timpl;
}

inline
void transaction::commit( void ) 
{ 
    timpl->commit(); 
}

inline
record_set transaction::query( const std::string& q )
{
    return timpl->query(q);
}

inline
void transaction::rollback( void ) 
{ 
    timpl->rollback(); 
}
/**
 * This class is a base representation of a Database Connection.
 * Its thread safety is being determined by the underlying implementation, but
 * you should not count on it...
 */
class db
{
private:
protected:
public:
   /**
    * We do nothing more here
    */
    db( );

   /**
    * Make sure we really disconnect here
    */
    virtual ~db( );

   /**
    * This Function is the FrontEnd function for connecting to a database. It
    * will internally do necessary checks and locking common for all databases,
    * and then call do_connect()
    * @return 0 on Success, vendor specific error code otherwise. Often this is
    * a constant from cerrno, or its negative.
    * @param dbh Hostname where the database resides
    * @param dbn DBName of the Database
    * @param dbu UserName for Database Login
    * @param dbpw Password for logging into the database
    * @param dbpar Vendor specific parameter string. Usually empty.
    */
    virtual int connect(  const string& dbh, const string& dbn,
	    		const string& dbu, const string& dbpw, const string& dbpar) = 0;

   /**
    * Disconnect from the database. In disconnected state, you cannot query the
    * database.
    * @return An error code, if any. 0 on Success.
    */
    virtual int disconnect( void ) = 0;

   /**
    * Start a Transaction.
    */
    virtual transaction_implementation& transact( transaction::isolation_level il = transaction::read_committed, const std::string& name = "default" ) = 0;

   /**
    * This sets the encoding of the client system. This might be useful if the
    * database has a different encoding, so they can be translated. The details
    * of this behaviour will certainly differ on implementations.
    */
    virtual int set_encoding( const std::string& ) = 0;

   /**
    * This is to check for connected database backend. 
    * @return true if the connection is established
    * @note A more sophisticated derived class will surely override this
    * function, since it can check more reliable for the connection state of
    * the database.
    */
    virtual bool is_connected( void ) const { return true; }
};
} // namespace db
} // namespace iwear
#endif

