/*
 *  OpenDBX - A simple but extensible database abstraction layer
 *  Copyright (C) 2004-2009 Norbert Sendetzky <norbert@linuxnetworks.de>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307 USA.
 */



#include <opendbx/api.h>
#include <stdexcept>
#include <vector>
#include <string>



#ifndef ODBX_API_HPP
#define ODBX_API_HPP



extern "C++" {



/**
 * OpenDBX C++ API
 *
 * The OpenDBX C++ API is an object-oriented database abstraction layer based
 * on the procedural C API of the OpenDBX library. The C++ API provides objects
 * encapsulating connections, statements, result sets and large objects.
 *
 * Using the API starts with establishing a connection to the database server by
 * creating an instance of the Conn class with the parameters backend, host and
 * port. Conn::getCapability() tests the implemented capabilites of the underlying
 * database library while Conn::getOption() and Conn::setOption() has be used to
 * test for and change a number of options. The options must be changed before
 * authenticating the connection with the Conn::bind() method to have any effect.
 * It's also possible to rebind a connection using different credentials after
 * Conn::unbind() had been called. Additionally, the Conn class is able to
 * escape potentially dangerous character sequences with Conn::escape() if e.g.
 * user input should be part of a statement as value.
 *
 * The Conn::create() method creates and initializes a new statement instance
 * from a SQL string. Currently, there are only simple statement objects
 * implemented, which needs to be complete statements which can be sent to the
 * database with Stmt::execute(). This method returns a Result object
 * encapsulating one or more result sets returned by the database depending on
 * the statement sent.
 *
 * Each result set must be retrieved using Result::getResult(), while
 * Result::getRows() fetches a row from the current result set if the statement
 * was a SELECT like statement. Otherwise, Result::rowsAffected() can be used
 * to get the number of rows that were touched by the statement. If the statement
 * may return rows, the Result::columnName() and Result::columnType() methods
 * are able to provide some informations about the columns indexed from 0 to n.
 * It's also possible to map the column name with the Result::columnPos() method
 * to the column index which is required be the other column methods. To get
 * the actual value and length of the content in the current row at the given
 * position, the Result::fieldValue() and Result::fieldLength() must be called.
 *
 * In case the unterlying database library requires special handling of large
 * objects (binary or text LOBs), the value of Result::fieldValue() has to be
 * feed into the Result::getLob() method. It returns a Lob object which enables
 * the application to read from and write to a large object using Lob::read()
 * respectively Lob::write(). This is only necessary if the Conn::getCapability()
 * method returns true when asking for ODBX_CAP_LO.
 *
 * If an error occurs in any of the object methods, the objects will throw an
 * instance of the Exception class with extends the runtime_error exception of
 * the STL. The instance contains an error message, the OpenDBX error code and
 * an error type indicating the severity of the error. This information can be
 * retrieved by the methods Exception::what(), Exception::getCode() and
 * Exception::getType().
 *
 * @author Norbert Sendetzky <norbert@linuxnetworks.de>
 * @version 1.0
 */
namespace OpenDBX
{
	using std::string;

	class Lob_Iface;
	class Result_Iface;
	class Stmt_Iface;
	class Conn_Iface;



	/**
	 * Exceptions thrown by the OpenDBX classes.
	 *
	 * Most calls to methods of OpenDBX objects does throw an exception in case
	 * an error occurs in the underlying database library. Additionally to other
	 * exceptions which inherit from the STL exception class it will not only
	 * contain a translated error message depending on the user settings but
	 * also a machine readable error code and an indicator for the severity of
	 * the eror.
	 *
	 * @author Norbert Sendetzky <norbert@linuxnetworks.de>
	 * @version 1.0
	 */
	class Exception : public std::runtime_error
	{
		/**
		 * Error code (negative).
		 */
		int m_error;

		/**
		 * Severity of error (negative: fatal, zero: success, positive: warning)
		 */
		int m_type;

	public:

		/**
		 * Initializes the exception object.
		 *
		 * The first parameter, the error message, should be the human readable
		 * description of what has gone wrong. It should also be already translated
		 * to the language of the user which depends on his environment settings
		 * when e.g GNU gettext is used. Errors thrown by the OpenDBX C++ library
		 * are already translated.
		 *
		 * The OpenDBX error code is the machine readable code for the error which
		 * has been occured.
		 *
		 * The last parameter must be a value indicating the severity of the
		 * thrown error. If the value is smaller than zero, the error is fatal
		 * and the connection to the database can't be recovered and has to be
		 * closed and reopened before the application can try to continue. In
		 * case it's greater than zero, the operation failed but the database
		 * connection is still usable. Zero represents a successful operation
		 * and shouldn't be used because an exception should only be thrown in
		 * error conditions.
		 *
		 * @param msg Human readable error message
		 * @param err OpenDBX error code
		 * @param type Severity of error (negative: fatal, zero: success, positive: warning)
		 * @return Exception
		 */
		Exception( const string& msg, int err, int type ) throw();

		/**
		 * Returns the OpenDBX error code related to the error.
		 *
		 * The machine readable code describing the error which occured can be
		 * used by the application to act differently depending on the specific
		 * error. Currently defined codes are:
		 *
		 * - ODBX_ERR_SUCCESS\n
		 *   The operation was successfully completed.
		 * - ODBX_ERR_BACKEND\n
		 *   An error occured in the native database library or in the
		 *   database server.
		 * - ODBX_ERR_NOCAP\n
		 *   The capability isn't available in the currently selected backend.
		 * - ODBX_ERR_PARAM\n
		 *   One of the given parameters is invalid and doesn't match the
		 *   expectations.
		 * - ODBX_ERR_NOMEM\n
		 *   An out of memory condition occured.
		 * - ODBX_ERR_SIZE\n
		 *   The internally allocated memory is unable to store the value.
		 * - ODBX_ERR_NOTEXIST\n
		 *   The backend library wasn't found or loading the library failed.
		 * - ODBX_ERR_NOOP\n
		 *   The required function isn't available or the operation isn't
		 *   possible in this backend.
		 * - ODBX_ERR_OPTION\n
		 *   The given option is unknown an therefore invalid.
		 * - ODBX_ERR_OPTRO\n
		 *   The requested option is read-only and its value can't be changed.
		 * - ODBX_ERR_OPTWR\n
		 *   Setting the given option to the new value failed.
		 * - ODBX_ERR_RESULT\n
		 *   Waiting for the result set after sending a statement to the
		 *   database server failed.
		 * - ODBX_ERR_NOTSUP\n
		 *   The requested functionality isn't supported by the backend.
		 * - ODBX_ERR_HANDLE\n
		 *   The internal data structure which should store the details for
		 *   accessing the database are invalid.
		 *
		 * @return Error code
		 */
		int getCode() const throw();

		/**
		 * Returns severity indicator.
		 *
		 * The returned value classifies the error thrown. In case it is negative,
		 * the error is fatal (e.g. the connection to the database is lost) and
		 * the application can't continue without closing and reopening the
		 * connection.
		 *
		 * If the value is positive, the database wasn't able to perform the
		 * requested action but the connection is still OK and can be used to
		 * send more requests to the database.
		 * On zero, everything was successfull and no error occured. This
		 * shouldn't happen when catching one of these exceptions.
		 *
		 * @return Severity of error (negative: fatal, zero: success, positive: warning)
		 */
		int getType() const throw();
	};



	/**
	 * Handling large objects if supported by the database.
	 *
	 * @author Norbert Sendetzky <norbert@linuxnetworks.de>
	 * @version 1.0
	 */
	class Lob
	{
		friend class Result;

		/**
		 * Private implementation of object.
		 */
		Lob_Iface* m_impl;

		/**
		 * Reference counter of copies.
		 */
		int* m_ref;

	protected:

		/**
		 * Default constructor.
		 *
		 * The default constructor isn't part of the public interface as the
		 * object must not be created manually. Instead, the Result::getLob()
		 * method is a factory for instances of the large object class.
		 *
		 * @return Lob instance
		 */
		Lob() throw() {};

		/**
		 * Create large object instance.
		 *
		 * The constructor isn't part of the public interface as the object must
		 * not be created manually. Instead, the Result::getLob()  method is a
		 * factory for instances of the large object class.
		 *
		 * @param impl Pointer to private implementation
		 * @return Lob instance
		 * @throws std::exception If an error occures
		 */
		Lob( Lob_Iface* impl );

	public:

		/**
		 * Destroy large object instance if no other references exist.
		 *
		 * Each large object uses a reference counter to remember if the
		 * internal variables are shared with other objects. If this isn't the
		 * case or if this object is the last one referencing the variables,
		 * the object is cleanup up and the allocated memory freed.
		 */
		~Lob() throw();

		/**
		 * Copy constructor.
		 *
		 * Enables the transfer of the internal state of an object \a ref of the same
		 * type to this object. Both objects share the same variables
		 * and the reference counter afterwards. The reference counter is
		 * incremented each time an object is copied and will be decremented if
		 * it is destroyed.
		 *
		 * @param ref Original large object instance
		 */
		Lob( const Lob& ref ) throw();

		/**
		 * Assign large object instance to another one.
		 *
		 * Assigns the internal state of an object \a ref of the same type to this
		 * object. Both objects share the same variables and the
		 * reference counter afterwards. The reference counter is incremented
		 * each time an object is copied and will be decremented if it is
		 * destroyed.
		 *
		 * @param ref Large object instance
		 * @return Large object reference of this instance
		 */
		Lob& operator=( const Lob& ref ) throw();

		/**
		 * Closes the large object and commits the changes.
		 *
		 * After reading from or writing new content into the large object, it
		 * should be closed to commit changes to the disk and clean up the
		 * resources. If this isn't done, the destructor of the object tries to
		 * close the large object automatically, but there's no guarantee it
		 * was successful as the destructor doesn't throw an exception in case
		 * of an error. Therefore, it's highly recommended to call this method
		 * once when you don't need the object any more.
		 *
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		void close();

		/**
		 * Reads content from large object into the buffer.
		 *
		 * To get the content of a large object, this method fetches the data
		 * in one or more pieces from the server and stores it into the user
		 * supplied buffer. The first call to read() will return the bytes from
		 * the beginning. The second and all other calls will store subsequent
		 * parts of the large object content into the buffer until the end of
		 * the data is reached. To reread the content a second time, you have
		 * to close the large object handle and reopen it again as some databases
		 * provide no way to reposition the internal file position indicator for
		 * the stream. The large object content fetched from the server is
		 * stored into the user supplied \a buffer up to \a buflen bytes.
		 *
		* The method returns the number of bytes placed into \a buffer, which may
		* be up to \a buflen bytes. If the end of the content is reached and no
		* more data is available, the return value will be 0 (zero).
		 *
		 * @param buffer Pointer to a byte array where the data should be written to
		 * @param buflen Length of the given buffer in bytes
		 * @return Number of bytes written into the buffer
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		ssize_t read( void* buffer, size_t buflen );

		/**
		 * Writes data from the buffer into the large object.
		 *
		 * It sends the data supplied in buffer to the server for storing it
		 * inside the large object. The function can be called more than once
		 * to add subsequent parts of the content to the object. If it isn't a
		 * new or empty object, the existing data will be overwritten and
		 * truncated to the new size. It's not possible to update only parts of
		 * the content as some databases doesn't support to position the
		 * internal file position indicator. The data which should be send to
		 * the server is read from \a buffer up to \a buflen bytes.
		 *
		 *The method returns the number of bytes read from \a buffer and sent to
		 * the database server, which may be up to \a buflen bytes. It isn't
		 * guaranteed that the complete chunk was sent to the server, so the
		 * returned size may be less than the value in \a buflen.
		 *
		 * @param buffer Pointer to a byte array where the content is stored
		 * @param buflen Length of the data in the buffer in bytes
		 * @return Number of bytes written into the large object
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		ssize_t write( void* buffer, size_t buflen );
	};



	/**
	 * Provides result sets from the database.
	 *
	 * @author Norbert Sendetzky <norbert@linuxnetworks.de>
	 * @version 1.0
	 */
	class Result
	{
		friend class Stmt;

		/**
		 * Private implementation of object.
		 */
		Result_Iface* m_impl;

		/**
		 * Reference counter of copies.
		 */
		int* m_ref;

	protected:

		/**
		 * Default constructor.
		 *
		 * The default constructor isn't part of the public interface as the
		 * object must not be created manually. Instead, the Stmt::execute()
		 * method is a factory for instances of the Result class.
		 *
		 * @return Result instance
		 */
		Result() throw() {};

		/**
		 * Creates a Result instance.
		 *
		 * The constructor isn't part of the public interface as the object must
		 * not be created manually. Instead, the Stmt::execute()  method is a
		 * factory for instances of the Result class.
		 *
		 * @param impl Pointer to private implementation
		 * @throws std::exception If an error occures
		 * @return Result instance
		 */
		Result( Result_Iface* impl );

	public:

		/**
		 * Destroys a Result instance if no other references exist.
		 *
		 * Each result object uses a reference counter to remember if the
		 * internal variables are shared with other objects. If this isn't the
		 * case or if this object is the last one referencing the variables,
		 * the object is cleanup up and the allocated memory freed.
		 */
		~Result() throw();

		/**
		 * Copy constructor.
		 *
		 * Enables the transfer of the internal state of an object \a ref of the same
		 * type to this object. Both objects share the same variables
		 * and the reference counter afterwards. The reference counter is
		 * incremented each time an object is copied and will be decremented if
		 * it is destroyed.
		 *
		 * @param ref Original result object instance
		 */
		Result( const Result& ref ) throw();

		/**
		 * Assigns a Result instance to another one.
		 *
		 * Assigns the internal state of an object \a ref of the same type to this
		 * object. Both objects share the same variables and the
		 * reference counter afterwards. The reference counter is incremented
		 * each time an object is copied and will be decremented if it is
		 * destroyed.
		 *
		 * @param ref Result instance
		 * @return Result reference of this instance
		 */
		Result& operator=( const Result& ref ) throw();

		/**
		 * Retrieves unfetched rows and cleans up the available result sets.
		 *
		 * After executing a statement, at least one result set is returned by
		 * the database server. In case of data manipulation statements, there
		 * are no rows returned but you have to clean up the result set
		 * nevertheless. This is usually done by calling and getResult() in a loop
		 * until it returns "done". In order to simplify application development,
		 * the finish() method does this for you.
		 *
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		void finish();

		/**
		 * Fetches one result set from the database server.
		 *
		 * Retrieves the result of a query statement from the database server.
		 * If the statement was an INSERT, UPDATE, DELETE or a similar
		 * statement, the number of affected rows is available via rowsAffected().
		 *
		 * The \a timeout parameter restricts the time the function is waiting for
		 * a result form the server. It may be NULL to wait until a result
		 * arrives. Otherwise, it can contain any number of seconds and
		 * microseconds in a timeval structure to wait for. The timeval structure
		 * must be set each time before calling getResult() because its content
		 * may get changed by the function. If the server doesn't respond within
		 * the timeout, the query isn't canceled! Instead, the next call to this
		 * function will wait for the same result set. Waiting the specified time
		 * may be implemented in the backends if it is possible, but there is no
		 * guarantee. If not, getResult() will return not before a responds
		 * arrives.
		 *
		 * Dependent on the native database library, it may be possible to
		 * retrieve all rows at once (if chunk is zero), one by one or more than
		 * one row at once. All positive values including zero are allowed as
		 * values for \a chunk If paging (more than one row at once) is not
		 * supported by the backend, it will use "one by one" or "all at once"
		 * if this is the only option provided.
		 *
		 * getResult() returns ODBX_RES_ROWS if a result set is available and
		 * ODBX_RES_DONE if no more results will be returned by the last
		 * successful query. ODBX_RES_NOROWS is returned if the statement was
		 * executed successfully but will not return a results set (like for
		 * INSERT, UPDATE and DELETE statements) and ODBX_RES_TIMEOUT indicates
		 * a timeout.
		 *
		 * @param timeout Pointer to a timeval struct specifying how long to wait for a result set from the database server
		 * @param chunk Number of rows to fetch at once from the database server (zero means all rows at once)
		 * @return Status or error code
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 * @see odbxres
		 */
		odbxres getResult( struct timeval* timeout = NULL, unsigned long chunk = 0 );

		/**
		 * Makes data of next row available.
		 *
		 * Retrieves the values of a row from the current result set returned
		 * by getResult(). Until this function is invoked, no row and field data
		 * is available via fieldLength() or fieldValue() and these functions
		 * will throw an exception.
		 *
		 * getRow() will return ODBX_ROW_NEXT as long as rows are available
		 * from the result set. After the last row has been made available,
		 * further calls to this function will return ODBX_ROW_DONE indicating
		 * that the result set doesn't contain more rows.
		 *
		 * @return Status of the attempt to fetch one more row
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		odbxrow getRow();

		/**
		 * Returns the number of rows affected by DELETE, INSERT of UPDATE statements.
		 *
		 * Returns the number of rows that have been changed by the current
		 * statement whose result set was retrieved by getResult() and zero
		 * if the database server didn't alter any rows. Affected rows are only
		 * returned for DELETE, INSERT or UPDATE statements and their concrete
		 * number depends on the database implementation. Some database server
		 * like MySQL may return a lower number than expected because they
		 * doesn't modify records whose values wouldn't change.
		 *
		 * @return Number of rows touched
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		uint64_t rowsAffected();

		/**
		 * Returns the number of columns available in this result set.
		 *
		 * The number of columns will never change within a result set with one
		 * notable exception: MySQL returns all outstanding rows of a previous
		 * result set first if they were not fetched completely by getRow()
		 * before. Therefore, the column count might change in this special
		 * situation.
		 *
		 * @return Number of columns
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		unsigned long columnCount();

		/**
		 * Maps the column name to the column number required by other methods.
		 *
		 * This method returns the index of the column which is named like the
		 * content of the string given via the parameter \a name. The column index will
		 * not change within the result set.
		 *
		 * @param name Name of the column in the result set
		 * @return Position of column in result set
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		unsigned long columnPos( const string& name );

		/**
		 * Returns the name of the column in the current result set.
		 *
		 * Gets the name of the column specified by \a pos in the current result
		 * set. The column names will not change within the result set with the
		 * exception of MySQL when the first result set wasn't retrieved
		 * completely before getResult() was called again.
		 *
		 * @param pos Position of column in result set
		 * @return Column name
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		const string columnName( unsigned long pos );

		/**
		 * Returns the type of the column in the current result set.
		 *
		 * The column type applies to all fields at the same position of the
		 * rows fetched via getRow(). The definitions are based on the SQL2003
		 * standard and the data types of the database server have to comply to
		 * the specification of the standard. These are:
		 *
		 * Exact numeric values:
		 * - ODBX_TYPE_BOOLEAN: True/false values
		 * - ODBX_TYPE_SMALLINT: Signed 16 bit integer
		 * -  ODBX_TYPE_INTEGER: Signed 32 bit integer
		 * -  ODBX_TYPE_BIGINT: Signed 64 bit integer
		 * -  ODBX_TYPE_DECIMAL: Exact signed numeric values with user defined precision
		 *
		 * Approximate numeric values:
		 * - ODBX_TYPE_REAL: Approximate numeric values (signed) with 32 bit precision
		 * - ODBX_TYPE_DOUBLE: Approximate numeric values (signed) with 64 bit precision
		 * - ODBX_TYPE_FLOAT: Approximate numeric values (signed) with user defined precision
		 *
		 * String values:
		 * - ODBX_TYPE_CHAR: Fixed number of characters
		 * - ODBX_TYPE_NCHAR: Fixed number of characters using a national character set
		 * - ODBX_TYPE_VARCHAR: Variable number of characters
		 * - ODBX_TYPE_NVARCHAR: Variable number of characters using a national character set
		 *
		 * Large objects:
		 * - ODBX_TYPE_CLOB: Large text object
		 * - ODBX_TYPE_NCLOB: Large text object using a national character set
		 * - ODBX_TYPE_XML: XML tree in text format
		 * - ODBX_TYPE_BLOB: Large binary object
		 *
		 * Date and time values:
		 * - ODBX_TYPE_TIME: Time including hours, minutes and seconds
		 * - ODBX_TYPE_TIME_TZ: Time with timezone information
		 * - ODBX_TYPE_TIMESTAMP: Date and time
		 * - ODBX_TYPE_TIMESTAMP_TZ: Date and time with timezone information
		 * - ODBX_TYPE_DATE: Date including year, month and day
		 * - ODBX_TYPE_INTERVAL: Date interval
		 *
		 * Arrays and sets:
		 * - ODBX_TYPE_ARRAY: Array of values
		 * - ODBX_TYPE_MULTISET: Associative arrays
		 *
		 * External links:
		 * - ODBX_TYPE_DATALINK: URI locators like URL links
		 *
		 * Data types provided by database implementations which are not covered
		 * by the SQL2003 standard are subsumed as ODBX_TYPE_UNKNOWN.
		 *
		 * @param pos Position of column in result set
		 * @return Column type
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 * @see odbxtype
		 */
		odbxtype columnType( unsigned long pos );

		/**
		 * Returns the size of the content in the current row at the specified postion.
		 *
		 * The field is part of the current row which was retrieved by the
		 * latest call to getRow() and is specified by the column index given by
		 * \a pos.
		 *
		 * @param pos Position of column in result set
		 * @return Size of the data in bytes
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		unsigned long fieldLength( unsigned long pos );

		/**
		 * Returns a pointer to the content in the current row at the specified postion.
		 *
		 * This function returns a pointer to the field data specified by the
		 * column index \a pos. The field is part of the current row which was
		 * retrieved by the latest call to getRow(). All values except binary
		 * objects are handed back as strings terminated by the zero character.
		 * This does also apply to numeric values, dates, etc. They have to be
		 * converted to their binary machine dependent representation before
		 * arithmetic operations can be done. If a value is undefined, i.e.
		 * "NULL" is attached to the field in the database, an equivalent NULL
		 * pointer is returned.
		 *
		 * @param pos Position of column in result set
		 * @return Pointer to the data
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		const char* fieldValue( unsigned long pos );

		/**
		 * Creates a large object instance if supported by the database.
		 *
		 * Returns a Lob class instance representing a large object stored in
		 * the database. It references the large object and provided methods for
		 * accessing and modifying its content.
		 *
		 * The parameter required by this method must be the value returned by
		 * the fieldValue() method of a large object column.
		 *
		 * This method must only be used if the underlying driver states that it
		 * supports large objects via the Conn::getCapabilities(). Otherwise,
		 * the content can be retrieved directly by the fieldValue() method.
		 *
		 * @param value Pointer to the content of a field returned by fieldValue()
		 * @return Large object instance
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 * @see Lob
		 */
		Lob getLob( const char* value );
	};



	/**
	 * Statement object.
	 *
	 * @author Norbert Sendetzky <norbert@linuxnetworks.de>
	 * @version 1.0
	 */
	class Stmt
	{
		friend class Conn;

		/**
		 * Private implementation of object.
		 */
		Stmt_Iface* m_impl;

		/**
		 * Reference counter of copies.
		 */
		int* m_ref;

	protected:

		/**
		 * Default constructor.
		 *
		 * The default constructor isn't part of the public interface as the
		 * object must not be created manually. Instead, the Conn::create()
		 * method is a factory for instances of the Stmt class.
		 *
		 * @return Statement instance
		 */
		Stmt() throw() {};

		/**
		 * Creates a statement instance.
		 *
		 * The constructor isn't part of the public interface as the object must
		 * not be created manually. Instead, the Conn::create()  method is a
		 * factory for instances of the Stmt class.
		 *
		 * @param impl Pointer to private implementation
		 * @throws std::exception If an error occures
		 * @return Statement instance
		 */
		Stmt( Stmt_Iface* impl );

	public:

		/**
		 * Statement objects which can be created.
		 *
		 * Currently, only simple processing of statements is supported which
		 * means that the statement sent to the database server consists of the
		 * statement and the parameters in text form. Later on, also prepared
		 * statements will be available which separates parsing and execution
		 * with different parameters.
		 */
		enum Type { Simple };

		/**
		 * Destroys the statement instance if no other references exist.
		 *
		 * Each statement object uses a reference counter to remember if the
		 * internal variables are shared with other objects. If this isn't the
		 * case or if this object is the last one referencing the variables,
		 * the object is cleaned up and the allocated memory freed.
		 */
		~Stmt() throw();

		/**
		 * Copy constructor.
		 *
		 * Enables the transfer of the internal state of an object \a ref of the same
		 * type to this object. Both objects share the same variables
		 * and the reference counter afterwards. The reference counter is
		 * incremented each time an object is copied and will be decremented if
		 * it is destroyed.
		 *
		 * @param ref Original statement object instance
		 */
		Stmt( const Stmt& ref ) throw();

		/**
		 * Assigns a statement instance to another one.
		 *
		 * Assigns the internal state of an object \a ref of the same type to this
		 * object. Both objects share the same variables and the
		 * reference counter afterwards. The reference counter is incremented
		 * each time an object is copied and will be decremented if it is
		 * destroyed.
		 *
		 * @param ref Stmt instance
		 * @return Statement reference of this instance
		 */
		Stmt& operator=( const Stmt& ref ) throw();

		/**
		 * Executes a statement and returns a Result instance.
		 *
		 * Sends the necessary data to the database server which will execute
		 * the statement and return one or more result sets afterwards. The
		 * result sets can be fetched via the returned Result object.
		 *
		 * @return Result instance
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 * @see Result
		 */
		Result execute();
	};



	/**
	 * Encapsulates a connection to a database.
	 *
	 * @author Norbert Sendetzky <norbert@linuxnetworks.de>
	 * @version 1.0
	 */
	class Conn
	{
		/**
		 * Private implementation of the connection object.
		 */
		Conn_Iface* m_impl;

		/**
		 * Reference counter of copies.
		 */
		int* m_ref;

	public:

		/**
		 * The default constructor for newly created connection objects without
		 * parameters.
		 *
		 * This is method is provided to enable programmers to use connection
		 * objects as member variables of other classes. They are initialized
		 * at construction time of the encapsulating object when no values
		 * for backend, host and port are available yet.
		 *
		 * It's necessary to replace the created object later on by a connection
		 * instance where the necessary parameters have been given via one of
		 * the other constructors. Calling one of the member functions of an
		 * instance created by the default constructor isn't possible and will
		 * throw an exception.
		 *
		 * @return Empty connection instance
		 * @see #Conn( const char*, const char*, const char* )
		 * @see #Conn( const string&, const string&, const string& )
		 */
		Conn() throw();

		/**
		 * Creates a connection object using C style string parameters.
		 *
		 * Initializes a new connection using the parameters \a backend, \a host and
		 * \a port, but doesn't open the connection to the database yet. This method
		 * allows C style strings as values for all parameters. Another constructor
		 * for C++ style strings is also available. It returns a new connection
		 * instance, which can be used to query options implemented by the driver
		 * or to create a statement. In case of an error, it throws an OpenDBX
		 * exception with error message, code and severity.
		 *
		 * The parameter \a backend is the name of the driver the OpenDBX library
		 * should use to connect to a database. The name must be one of the
		 * implemented and available drivers on the system and is case sensitive.
		 * All driver names are in lower case, e.g. "mysql".
		 *
		 * Depending on the database driver, \a host can have different meanings.
		 * Normally, it's the name or IP address of the server hosting the
		 * database server application. In case of serverless database
		 * implementations like SQLite it's the directory path where the database
		 * file is located. The path must contain the platform specific path
		 * separators like slash ("/") on Unix-like systems and backslash ("\")
		 * on Windows systems. Also the path must end with the path separator
		 * like "/path/to/file/".
		 *
		 * Furthermore \a port can be the number or name the database server
		 * application is listening to. If a name instead of the number is
		 * allowed depends on the database client library but the number as
		 * string does always work. If an empty string is given, the default
		 * port of the database server application is used by the database
		 * client library.
		 *
		 * @param backend Name of the backend module to use
		 * @param host Name or IP address of the database server
		 * @param port Name or number of the port used by the database server
		 * @return Connection instance
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 * @see #Conn( const string&, const string&, const string& )
		 */
		Conn( const char* backend, const char* host = "", const char* port = "" );

		/**
		 * Creates a connection object using C++ style string parameters.
		 *
		 * Initializes a new connection using the parameters backend, host and
		 * port, but doesn't open the connection to the database yet. This method
		 * allows C++ style strings as values for all parameters. Another
		 * construtor for C style strings is also available. It returns a new
		 * connection instance, which can be used to query options implemented
		 * by the driver or to create a statement. In case of an error, it throws
		 * an OpenDBX exception with error message, code and severity.
		 *
		 * The parameter \a backend is the name of the driver the OpenDBX library
		 * should use to connect to a database. The name must be one of the
		 * implemented and available drivers on the system and is case sensitive.
		 * All driver names are in lower case, e.g. "mysql".
		 *
		 * Depending on the database driver, \a host can have different mearings.
		 * Normally, it's the name or IP address of the server hosting the
		 * database server application. In case of serverless database
		 * implementations like SQLite it's the directory path where the database
		 * file is located. The path must contain the platform specific path
		 * separators like slash ("/") on Unix-like systems and backslash ("\")
		 * on Windows systems. Also the path must end with the path separator
		 * like "/path/to/file/".
		 *
		 * Furthermore \a port can be the number or name the database server
		 * application is listening to. If a name instead of the number is
		 * allowed depends on the database client library but the number as
		 * string does always work. If an empty string is given, the default
		 * port of the database server application is used by the database
		 * client library.
		 *
		 * @param backend Name of the backend module to use
		 * @param host Name or IP address of the database server
		 * @param port Name or number of the port used by the database server
		 * @return Connection instance
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 * @see #Conn( const char*, const char*, const char* )
		 */
		Conn( const string& backend, const string& host = "", const string& port = "" );

		/**
		 * Destroys the connection instance if no other references exist.
		 *
		 * Each connection object uses a reference counter to remember if the
		 * connection is shared with other objects. If this isn't the case or
		 * if this object is the last one referencing the connection, the
		 * connection is closed and the allocated memory is freed.
		 */
		~Conn() throw();

		/**
		 * Copy constructor.
		 *
		 * Enables the transfer of the internal state of an object \a ref of the same
		 * type to this object. Both objects share the same database connection
		 * and the reference counter afterwards. The reference counter is
		 * incremented each time an object is copied and will be decremented if
		 * it is destroyed.
		 *
		 * @param ref Original connection object instance
		 */
		Conn( const Conn& ref ) throw();

		/**
		 * Assigns a connection instance to another one.
		 *
		 * Assigns the internal state of an object \a ref of the same type to this
		 * object. Both objects share the same database connection and the
		 * reference counter afterwards. The reference counter is incremented
		 * each time an object is copied and will be decremented if it is
		 * destroyed.
		 *
		 * @param ref Connection instance
		 * @return Connection reference of this instance
		 */
		Conn& operator=( const Conn& ref ) throw();

		/**
		 * Authenticates the user and selects the database using C style string
		 * parameters.
		 *
		 * After initializing the object instance with one of the constructors
		 * taking a backend, host and port string as parameter, it's necessary
		 * to authenticate the user and select a database. Depending on the
		 * database client library, it also establishes the connection to the
		 * database server. This method accepts C style strings for the database
		 * name, the user name and the password.
		 *
		 * The first parameter, the name of the database will be used to select
		 * the database all further commands are operating on. The database is
		 * the container for the tables, views, etc., which store the records
		 * and provide access to them.
		 *
		 * Authentication is done in most cases by a combination of a user name
		 * and a password. If the user name is known by the database server and
		 * the supplied password matches with the stored one, the database
		 * server will allow the user to operate on the selected database and
		 * its tables provided the user has permissions to read and/or modify
		 * the content.
		 *
		 * The \a method parameter can be used to select different methods of
		 * authentication. At the moment, only simple authentication
		 * (ODBX_BIND_SIMPLE) with user name and password is available.
		 *
		 * @param database Name of the database managed by the database server
		 * @param who Name of the user account known by the database server
		 * @param cred Necessary credential which belongs to the user account
		 * @param method Method used for authentication
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		void bind( const char* database, const char* who = "", const char* cred = "", odbxbind method = ODBX_BIND_SIMPLE );

		/**
		 * Authenticates the user and selects the database using C++ style string
		 * parameters.
		 *
		 * After initializing the object instance with one of the constructors
		 * taking a backend, host and port string as parameter, it's necessary
		 * to authenticate the user and select a database. Depending on the
		 * database client library, it also establishes the connection to the
		 * database server. This method accepts C++ style strings for the
		 * database name, the user name and the password.
		 *
		 * The first parameter, the name of the database will be used to select
		 * the database all further commands are operating on. The database is
		 * the container for the tables, views, etc., which store the records
		 * and provide access to them.
		 *
		 * Authentication is done in most cases by a combination of a user name
		 * and a password. If the user name is known by the database server and
		 * the supplied password matches with the stored one, the database
		 * server will allow the user to operate on the selected database and
		 * its tables provided the user has permissions to read and/or modify
		 * the content.
		 *
		 * The \a method parameter can be used to select different methods of
		 * authentication. At the moment, only simple authentication
		 * (ODBX_BIND_SIMPLE) with user name and password is available.
		 *
		 * @param database Name of the database managed by the database server
		 * @param who Name of the user account known by the database server
		 * @param cred Necessary credential which belongs to the user account
		 * @param method Method used for authentication
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		void bind( const string& database, const string& who = "", const string& cred = "", odbxbind method = ODBX_BIND_SIMPLE );

		/**
		 * Releases the connection to the database and resets the authentication
		 * status.
		 *
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		void unbind();

		/**
		 * Cleans up the connection object.
		 *
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		void finish();

		/**
		 * Tests if the database driver module does understand certain extensions.
		 *
		 * The OpenDBX library consists of a basic set of functions that must be
		 * implemented by all drivers and optional sets for additional
		 * functionality. This method allows an application to ask the driver
		 * selected by the first parameter of the constructor of this object if
		 * it supports one or more optional sets. The available sets and its
		 * constants are:
		 *
		 * - ODBX_CAP_BASIC\n
		 *   The core function set which have to be implemented by all backends.
		 *   It consists of all functions necessary to connect to, send textual
		 *   queries to and process simple results returned from the database
		 *   server as well as error handling functions.
		 * - ODBX_CAP_LO\n
		 *   The function set for handling large objects whose content isn't
		 *   accessible by the basic function. Currently, Firebird/Interbase
		 *   and Oracle requires using the LOB functions.
		 *
		 * The basic set makes sure that all drivers can handle connections to
		 * the databases, send statements and retrieve results. It's supported
		 * by all drivers and usually don't have to be checked.
		 *
		 * Some databases client libraries provide the content of large objects
		 * not via the basic functions. Instead, the Result::fieldValue() method
		 * returns only a handle to the large object and reading or modifying
		 * the content of this data object requires calling additional methods.
		 *
		 * @param cap Constant of the capability
		 * @return True if supported, false if not
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		bool getCapability( odbxcap cap );

		/**
		 * Gets the value of a certain option provided by the database driver module.
		 *
		 * It asks the backend module for implemented options and their current
		 * values. This function can be used at every stage and its primary use
		 * is to find out supported features of the backend module. This features
		 * can be enable with setOption() before the connection to the database
		 * server is established by calling bind().
		 *
		 * There are several option values defined as named constants in the
		 * opendbx/api.h header file. A few of them are for informational purpose
		 * only while most of the options can also be set to different values
		 * by setOption() to change the behavior of the backend module. These
		 * options are:
		 *
		 * - ODBX_OPT_API_VERSION\n
		 *   The API version implemented by the backend. It returns a five digit
		 *   number representing the API version of the backend module in the
		 *   form XYYZZ where X is the major number, YY the revision and ZZ the
		 *   minor number of the API.
		 * - ODBX_OPT_THREAD_SAFE\n
		 *   If it is safe to use this backend and especially the native database
		 *   client library in an application which uses threads where more than
		 *   one thread opens database connections via the OpenDBX library.
		 * - ODBX_OPT_TLS\n
		 *   The database client library may support transmitting all data
		 *   securely by encrypting the network traffic via SSL or TLS.
		 * - ODBX_OPT_MULTI_STATEMENTS\n
		 *   The database server may be able to support multiple SQL statements
		 *   in one string sent to the database.
		 * - ODBX_OPT_PAGED_RESULTS\n
		 *   All database servers and client libraries are able to transfer the
		 *   records row by row. Some of them can also transfer multiple rows
		 *   or even all at once to minimize server load, network traffic and
		 *   latency. The downside of this is an increased memory consumption.
		 * - ODBX_OPT_COMPRESS\n
		 *   Support of compressed network traffic between database client and
		 *   server. This can lead to higher throughput if the network is the
		 *   bottleneck.
		 * - ODBX_OPT_MODE\n
		 *   Some database servers support different modes of operation, e.g.
		 *   modes for compliance to other SQL implementations or completely
		 *   different query languages.
		 *
		 * The parameter \a value must be a pointer to an integer variable where
		 * the backend module will store the result for the supplied option. If
		 * it's not stated otherwise, the value assigned to the this parameter
		 * will be of boolean nature and therefore is ODBX_ENABLE for a supported
		 * option or ODBX_DISABLE for an option which isn't supported.
		 *
		 * @param option Constant of the option
		 * @param value Pointer to memory where the result is stored
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		void getOption( odbxopt option, void* value );

		/**
		 * Sets a certain option provided by the database driver module.
		 *
		 * Changes the value of the specified option in the backend module or
		 * the native database library. Before trying to set an option, it should
		 * be tested with getOption() first to ensure that it is supported by
		 * the backend. Almost all options need to be set before connecting to
		 * the database server using bind() to take any effect.
		 *
		 * There are several option values defined as named constants in the
		 * opendbx/api.h header file. The possible options are:
		 *
		 * - ODBX_OPT_TLS\n
		 *   Use encryption to transmit all data securely over the network via
		 *   SSL or TLS. This option can be set to ODBX_TLS_NEVER (the default
		 *   value) to prevent encrpytion, ODBX_TLS_ALWAYS to enforce encryption
		 *   and to fail if it can't be used between the client library and the
		 *   server or ODBX_TLS_TRY to use encryption if possible with the
		 *   option to fall back to a connection which isn't encrypted.
		 * - ODBX_OPT_MULTI_STATEMENTS\n
		 *   Enables the database server to accept multiple statements in one
		 *   string to the database if the value of value is set to ODBX_ENABLE.
		 *   Although, it might be possible to disable it by setting it to
		 *   ODBX_DISABLE.
		 * - ODBX_OPT_PAGED_RESULTS\n
		 *   All database servers and client libraries are able to transfer the
		 *   records row by row. Some of them can also transfer multiple rows
		 *   or even all at once to minimize server load, network traffic and
		 *   latency. The downside of this is an increased memory consumption.
		 *   If paged results are supported by the backend, passing positive
		 *   values will fetch the specified number of records at once from the
		 *   database server. The value of zero ("0") is special in this case
		 *   because it asks the backend module to retrieve all records at once.
		 * - ODBX_OPT_COMPRESS\n
		 *   Enable compressed network traffic between database client and
		 *   server. This can maximize the throughput if the network is the
		 *   bottleneck. Pass an integer variable with ODBX_ENABLE to enable
		 *   compression or with ODBX_DISABLE to disable it for this connection.
		 * - ODBX_OPT_MODE\n
		 *   Some database servers support different modes of operation, e.g.
		 *   modes for compliance to other SQL implementations or completely
		 *   different query languages. The value for this option must point to
		 *   a zero terminated string.
		 *
		 * If not stated otherwise, the type of the variable passed to the second
		 * parameter named \a value must be an integer pointer. Its values
		 * must be in the range specified by the option being changed.
		 *
		 * @param option Constant of the option
		 * @param value Pointer to memory which contains the new value
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		void setOption( odbxopt option, void* value );

		/**
		 * Escapes potentially dangerous characters in user input using a C style buffer.
		 *
		 * For preventing SQL injection attacks which can have desasterous
		 * effects, all text input that will be part of an SQL statement must be
		 * escaped. This does also apply to user content that is already stored
		 * in the database and should be copied to another record or stored
		 * again as the escaping is removed before the database server writes
		 * the content to disk.
		 *
		 * The first parameter must contain the character sequence that should
		 * be escaped as C style string. This string itself won't be modified
		 * by this method.
		 *
		 * The escaped string will be written to the third parameter named
		 * \a to, which have to be also an C++ style string. After transforming
		 * the input to an escaped string, the result may be more then twice
		 * the size of the original input. The additional escape sequences
		 * aren't stored in the database column so only the original string will
		 * be written to the disk.
		 *
		 * A C++ reference of the third parameter containing the escaped string
		 * afterwards is also returned by this method to providing the possibility
		 * to write more elegant code.
		 *
		 * @param from Input string with which may contain dangerous characters
		 * @param fromlen Size of the input string to escape in bytes
		 * @param to String instance where the escaped characters should be written to
		 * @return Reference to the second parameter containing the escaped characters
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		string& escape( const char* from, unsigned long fromlen, string& to );

		/**
		 * Escapes potentially dangerous characters in user input using a C++
		 * style string parameter.
		 *
		 * For preventing SQL injection attacks which can have desasterous
		 * effects, all text input that will be part of an SQL statement must be
		 * escaped. This does also apply to user content that is already stored
		 * in the database and should be copied to another record or stored
		 * again as the escaping is removed before the database server writes
		 * the content to disk.
		 *
		 * The first parameter must contain the character sequence that should
		 * be escaped as C++ style string. This string itself won't be modified
		 * by this method.
		 *
		 * The escaped string will be written to the third parameter named
		 * \a to, which have to be also an C++ style string. After transforming
		 * the input to an escaped string, the result may be more then twice
		 * the size of the original input. The additional escape sequences
		 * aren't stored in the database column so only the original string will
		 * be written to the disk.
		 *
		 * A C++ reference of the second parameter containing the escaped string
		 * afterwards is also returned by this method too, providing the possibility
		 * to write more elegant code.
		 *
		 * @param from Input string with which may contain dangerous characters
		 * @param to String instance where the escaped characters should be written to
		 * @return Reference to the second parameter containing the escaped characters
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 */
		string& escape( const string& from, string& to );

		/**
		 * Creates a statement object from a SQL text string using a C style buffer.
		 *
		 * This method returns an instance of the Stmt class that contains the
		 * statement sent to the database server later on. Currently, only simple
		 * statements are supported, which are sent to the database server for
		 * parsing and returning the result after calling Stmt::execute(). Later
		 * on also prepared statements will be possible which are parsed by the
		 * database server when creating the object and only the parameters
		 * will be sent to the database server on execution. This can speed up
		 * processing especially if the statement is executed multiple times
		 * with different content for the parameters.
		 *
		 * The parameter named \a sql must contain the SQL text string that should be
		 * sent to the database server for execution. It have to be a C style
		 * buffer in this case. For a reference of valid SQL statements, please
		 * have a look at the documentation of your database server.
		 *
		 * The length of the statement excluding the trailing "0" byte should
		 * be given via the second parameter \a size. If the length of the statement is
		 * unknown, you can also supply zero (0) as size value which is also the
		 * default value if you hand over only one parameter. In this case, the
		 * length of the string is calculated internally by this function before
		 * the statement is given to the native database library.
		 *
		 * Via the last parameter it can be selected how the statement should
		 * be treated internally by the OpenDBX and the native database library.
		 * Currently, only simple processing is available which sends complete
		 * SQL statements including its parameters as string to the database
		 * server for parsing and execution. Later on, also prepared statement
		 * handling will be available which parses the statements first and
		 * sends only the parameters to the server before execution. This
		 * parameter is also optional.
		 *
		 * The returned object is representing the given statement, which can
		 * be executed later on. The statement is only valid for the current
		 * connection and as soon as the connection gets invalid or is closed,
		 * working with this object will throw an error.
		 *
		 * @param sql SQL text string containing a valid statement understood by the database server
		 * @param size Size of the SQL text string in bytes
		 * @param type Type of statement object that should be created
		 * @return Statement instance bound to this connection
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 * @see Stmt
		 */
		Stmt create( const char* sql, unsigned long size = 0, Stmt::Type type = Stmt::Simple );

		/**
		 * Creates a statement object from a SQL text string using a C++ string.
		 *
		 * This method returns an instance of the Stmt class that contains the
		 * statement sent to the database server later on. Currently, only simple
		 * statements are supported, which are sent to the database server for
		 * parsing and returning the result after calling Stmt::execute(). Later
		 * on also prepared statements will be possible which are parsed by the
		 * database server when creating the object and only the parameters
		 * will be sent to the database server on execution. This can speed up
		 * processing especially if the statement is executed multiple times
		 * with different content for the parameters.
		 *
		 * The parameter named \a sql must contain the SQL text string that should be
		 * sent to the database server for execution. It have to be a C++ style
		 * string in this case. For a reference of valid SQL statements, please
		 * have a look at the documentation of your database server.
		 *
		 * Via the last parameter \a type it can be selected how the statement should
		 * be treated internally by the OpenDBX and the native database library.
		 * Currently, only simple processing is available which sends complete
		 * SQL statements including its parameters as string to the database
		 * server for parsing and execution. Later on, also prepared statement
		 * handling will be available which parses the statements first and
		 * sends only the parameters to the server before execution. This
		 * parameter is also optional.
		 *
		 * The returned object is representing the given statement, which can
		 * be executed later on. The statement is only valid for the current
		 * connection and as soon as the connection gets invalid or is closed,
		 * working with this object will throw an error.
		 *
		 * @param sql SQL text string containing a valid statement understood by the database server
		 * @param type Type of statement object that should be created
		 * @return Statement instance bound to this connection
		 * @throws std::invalid_argument If the object was only initialized by the default constructor
		 * @throws OpenDBX::Exception If the underlying database library returns an error
		 * @see Stmt
		 */
		Stmt create( const string& sql, Stmt::Type type = Stmt::Simple );
	};



}   // namespace OpenDBX



}   // extern C++



#endif
