/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/
#include <stdio.h>
#include "mysqlc_connection.hxx"
#include "mysqlc_propertyids.hxx"
#include "mysqlc_resultset.hxx"
#include "mysqlc_statement.hxx"
#include "mysqlc_general.hxx"

#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/sdbc/FetchDirection.hpp>
#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
#include <com/sun/star/sdbc/ResultSetType.hpp>

#include <cppconn/connection.h>
#include <cppconn/exception.h>
#include <cppconn/statement.h>
#include <cppuhelper/typeprovider.hxx>
#include <osl/diagnose.h>
#include <osl/thread.h>

#define USE_CPP_CONN 1

using namespace connectivity::mysqlc;
//------------------------------------------------------------------------------
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::sdbc;
using namespace com::sun::star::sdbcx;
using namespace com::sun::star::container;
using namespace com::sun::star::io;
using namespace com::sun::star::util;
using ::osl::MutexGuard;
using ::rtl::OUString;

#include <stdio.h>

/* {{{ OConnection::OCommonStatement() -I- */
OCommonStatement::OCommonStatement(OConnection* _pConnection, sql::Statement *_cppStatement) 
	:OCommonStatement_IBase(m_aMutex)
	,OPropertySetHelper(OCommonStatement_IBase::rBHelper)
    ,OStatement_CBase( (::cppu::OWeakObject*)_pConnection, this )
	,m_pConnection(_pConnection)
	,cppStatement(_cppStatement)
	,rBHelper(OCommonStatement_IBase::rBHelper)
{
	OSL_TRACE("OCommonStatement::OCommonStatement");
	m_pConnection->acquire();
}
/* }}} */


/* {{{ OConnection::~OCommonStatement() -I- */
OCommonStatement::~OCommonStatement()
{
	OSL_TRACE("OCommonStatement::~OCommonStatement");
}
/* }}} */


/* {{{ OConnection::disposeResultSet() -I- */
void OCommonStatement::disposeResultSet()
{
	OSL_TRACE("OCommonStatement::disposeResultSet");
	// free the cursor if alive
	delete cppStatement;
	cppStatement = NULL;
}
/* }}} */


/* {{{ OConnection::disposing() -I- */
void OCommonStatement::disposing()
{
	OSL_TRACE("OCommonStatement::disposing");
	MutexGuard aGuard(m_aMutex);

	disposeResultSet();

    if (m_pConnection) {
		m_pConnection->release();
		m_pConnection = NULL;
	}
	delete cppStatement;

    dispose_ChildImpl();
	OCommonStatement_IBase::disposing();
}
/* }}} */


/* {{{ OCommonStatement::queryInterface() -I- */
Any SAL_CALL OCommonStatement::queryInterface(const Type & rType)
	throw(RuntimeException)
{
	OSL_TRACE("OCommonStatement::queryInterface");
	Any aRet = OCommonStatement_IBase::queryInterface(rType);
	if (!aRet.hasValue()) {
		aRet = OPropertySetHelper::queryInterface(rType);
	}
	return aRet;
}
/* }}} */


/* {{{ OCommonStatement::getTypes() -I- */
Sequence< Type > SAL_CALL OCommonStatement::getTypes()
	throw(RuntimeException)
{
	OSL_TRACE("OCommonStatement::getTypes");
	::cppu::OTypeCollection aTypes(	::getCppuType( (const Reference< XMultiPropertySet > *)0 ),
									::getCppuType( (const Reference< XFastPropertySet > *)0 ),
									::getCppuType( (const Reference< XPropertySet > *)0 ));

	return concatSequences(aTypes.getTypes(), OCommonStatement_IBase::getTypes());
}
/* }}} */


/* {{{ OCommonStatement::cancel() -I- */
void SAL_CALL OCommonStatement::cancel()
	throw(RuntimeException)
{
	OSL_TRACE("OCommonStatement::cancel");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);
	// cancel the current sql statement
}
/* }}} */


/* {{{ OCommonStatement::close() -I- */
void SAL_CALL OCommonStatement::close()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::close");
	/*
	  We need a block for the checkDisposed call. 
	  After the check we can call dispose() as we are not under lock ??
	*/
	{
		MutexGuard aGuard(m_aMutex);
		checkDisposed(rBHelper.bDisposed);
	}
	dispose();
}
/* }}} */


/* {{{ OStatement::clearBatch() -I- */
void SAL_CALL OStatement::clearBatch()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OStatement::clearBatch");
	// if you support batches clear it here
}
/* }}} */


/* {{{ OStatement::execute() -I- */
sal_Bool SAL_CALL OCommonStatement::execute(const OUString& sql)
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::execute");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);
    const ::rtl::OUString sSqlStatement = m_pConnection->transFormPreparedStatement( sql );

    sal_Bool success = false;
	try {
		success = cppStatement->execute(OUStringToOString(sSqlStatement, m_pConnection->getConnectionSettings().encoding).getStr())? sal_True:sal_False;
	} catch (sql::SQLException &e) {
        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
	}
    return success;
}
/* }}} */


/* {{{ OStatement::executeQuery() -I- */
Reference< XResultSet > SAL_CALL OCommonStatement::executeQuery(const OUString& sql)
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::executeQuery");

	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);
    const ::rtl::OUString sSqlStatement = m_pConnection->transFormPreparedStatement(sql);

    Reference< XResultSet > xResultSet;
	try {
		std::auto_ptr< sql::ResultSet > rset(cppStatement->executeQuery(OUStringToOString(sSqlStatement, m_pConnection->getConnectionEncoding()).getStr()));
		xResultSet = new OResultSet(this, rset.get(), m_pConnection->getConnectionEncoding());
		rset.release();
	} catch (sql::SQLException &e) {
        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
	}
    return xResultSet;
}
/* }}} */


/* {{{ OStatement::getConnection() -I- */
Reference< XConnection > SAL_CALL OCommonStatement::getConnection()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::getConnection");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);

	// just return(our connection here
	return ((Reference< XConnection >)m_pConnection);
}
/* }}} */


/* {{{ OStatement::getUpdateCount() -I- */
sal_Int32 SAL_CALL OCommonStatement::getUpdateCount()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::getUpdateCount");
	return 0;
}
/* }}} */


/* {{{ OStatement::queryInterface() -I- */
Any SAL_CALL OStatement::queryInterface(const Type & rType)
	throw(RuntimeException)
{
	OSL_TRACE("OStatement::queryInterface");
	Any aRet = ::cppu::queryInterface(rType,static_cast< XBatchExecution*> (this));
	if (!aRet.hasValue()) {
		aRet = OCommonStatement::queryInterface(rType);
	}
	return (aRet);
}
/* }}} */


/* {{{ OStatement::addBatch() -I- */
void SAL_CALL OStatement::addBatch(const OUString& sql)
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OStatement::addBatch");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);

	m_aBatchList.push_back(sql);
}
/* }}} */


/* {{{ OStatement::executeBatch() -I- */
Sequence< sal_Int32 > SAL_CALL OStatement::executeBatch()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OStatement::executeBatch");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);

	Sequence< sal_Int32 > aRet = Sequence< sal_Int32 >();
	return aRet;
}
/* }}} */


/* {{{ OCommonStatement::executeUpdate() -I- */
sal_Int32 SAL_CALL OCommonStatement::executeUpdate(const OUString& sql)
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::executeUpdate");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);
    const ::rtl::OUString sSqlStatement = m_pConnection->transFormPreparedStatement(sql);

    sal_Int32 affectedRows = 0;
	try {
		affectedRows = cppStatement->executeUpdate(OUStringToOString(sSqlStatement, m_pConnection->getConnectionEncoding()).getStr());
	} catch (sql::SQLException &e) {
        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
	}
    return affectedRows;
}
/* }}} */


/* {{{ OCommonStatement::getResultSet() -I- */
Reference< XResultSet > SAL_CALL OCommonStatement::getResultSet()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::getResultSet");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);

    Reference< XResultSet > xResultSet;
	try {
		std::auto_ptr< sql::ResultSet > rset(cppStatement->getResultSet());
		xResultSet = new OResultSet(this, rset.get(), m_pConnection->getConnectionEncoding());
		rset.release();
	} catch (sql::SQLException &e) {
        mysqlc_sdbc_driver::translateAndThrow(e, *this, m_pConnection->getConnectionEncoding());
	}
    return xResultSet;
}
/* }}} */


/* {{{ OCommonStatement::getMoreResults() -I- */
sal_Bool SAL_CALL OCommonStatement::getMoreResults()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::getMoreResults");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);

	// if your driver supports more than only one resultset 
	// and has one more at this moment return(true
	return (sal_False);
}
/* }}} */


/* {{{ OCommonStatement::getWarnings() -I- */
Any SAL_CALL OCommonStatement::getWarnings()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::getWarnings");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);

	return makeAny(m_aLastWarning);
}
/* }}} */


/* {{{ OCommonStatement::clearWarnings() -I- */
void SAL_CALL OCommonStatement::clearWarnings()
	throw(SQLException, RuntimeException)
{
	OSL_TRACE("OCommonStatement::clearWarnings");
	MutexGuard aGuard(m_aMutex);
	checkDisposed(rBHelper.bDisposed);

	m_aLastWarning = SQLWarning();
}
/* }}} */


/* {{{ OCommonStatement::createArrayHelper() -I- */
::cppu::IPropertyArrayHelper* OCommonStatement::createArrayHelper( ) const
{
	OSL_TRACE("OCommonStatement::createArrayHelper");
	// this properties are define by the service statement
	// they must in alphabetic order
	Sequence< Property > aProps(10);
	Property* pProperties = aProps.getArray();
	sal_Int32 nPos = 0;
	DECL_PROP0(CURSORNAME,	OUString);
	DECL_BOOL_PROP0(ESCAPEPROCESSING);
	DECL_PROP0(FETCHDIRECTION,sal_Int32);
	DECL_PROP0(FETCHSIZE,	sal_Int32);
	DECL_PROP0(MAXFIELDSIZE,sal_Int32);
	DECL_PROP0(MAXROWS,		sal_Int32);
	DECL_PROP0(QUERYTIMEOUT,sal_Int32);
	DECL_PROP0(RESULTSETCONCURRENCY,sal_Int32);
	DECL_PROP0(RESULTSETTYPE,sal_Int32);
	DECL_BOOL_PROP0(USEBOOKMARKS);

	return new ::cppu::OPropertyArrayHelper(aProps);
}
/* }}} */


/* {{{ OCommonStatement::getInfoHelper() -I- */
::cppu::IPropertyArrayHelper & OCommonStatement::getInfoHelper()
{
	OSL_TRACE("OCommonStatement::getInfoHelper");
	return(*const_cast<OCommonStatement*>(this)->getArrayHelper());
}
/* }}} */


/* {{{ OCommonStatement::convertFastPropertyValue() -I- */
sal_Bool OCommonStatement::convertFastPropertyValue(
		Any & /* rConvertedValue */, Any & /* rOldValue */,
		sal_Int32 /* nHandle */, const Any& /* rValue */)
	throw (IllegalArgumentException)
{
	OSL_TRACE("OCommonStatement::convertFastPropertyValue");
	sal_Bool bConverted = sal_False;
	// here we have to try to convert
	return bConverted;
}
/* }}} */


/* {{{ OCommonStatement::setFastPropertyValue_NoBroadcast() -I- */
void OCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& /* rValue */)
	throw (Exception)
{
	OSL_TRACE("OCommonStatement::setFastPropertyValue_NoBroadcast");
	// set the value to what ever is nescessary
	switch (nHandle) {
		case PROPERTY_ID_QUERYTIMEOUT:
		case PROPERTY_ID_MAXFIELDSIZE:
		case PROPERTY_ID_MAXROWS:
		case PROPERTY_ID_CURSORNAME:
		case PROPERTY_ID_RESULTSETCONCURRENCY:
		case PROPERTY_ID_RESULTSETTYPE:
		case PROPERTY_ID_FETCHDIRECTION:
		case PROPERTY_ID_FETCHSIZE:
		case PROPERTY_ID_ESCAPEPROCESSING:
		case PROPERTY_ID_USEBOOKMARKS:
		default:
			;
	}
}
/* }}} */


/* {{{ OCommonStatement::getFastPropertyValue() -I- */
void OCommonStatement::getFastPropertyValue(Any& _rValue, sal_Int32 nHandle) const
{
	OSL_TRACE("OCommonStatement::getFastPropertyValue");
	switch (nHandle)	{
		case PROPERTY_ID_QUERYTIMEOUT:
		case PROPERTY_ID_MAXFIELDSIZE:
		case PROPERTY_ID_MAXROWS:
		case PROPERTY_ID_CURSORNAME:
		case PROPERTY_ID_RESULTSETCONCURRENCY:
		case PROPERTY_ID_RESULTSETTYPE:
		case PROPERTY_ID_FETCHDIRECTION:
		case PROPERTY_ID_FETCHSIZE:
		case PROPERTY_ID_ESCAPEPROCESSING:
			break;
		case PROPERTY_ID_USEBOOKMARKS:
            _rValue <<= sal_False;
            break;
		default:
			;
	}
}
/* }}} */

IMPLEMENT_SERVICE_INFO(OStatement,"com.sun.star.sdbcx.OStatement","com.sun.star.sdbc.Statement");

/* {{{ OCommonStatement::acquire() -I- */
void SAL_CALL OCommonStatement::acquire()
	throw()
{
	OSL_TRACE("OCommonStatement::acquire");
	OCommonStatement_IBase::acquire();
}
/* }}} */


/* {{{ OCommonStatement::release() -I- */
void SAL_CALL OCommonStatement::release()
	throw()
{
	OSL_TRACE("OCommonStatement::release");
    relase_ChildImpl();
}
/* }}} */


/* {{{ OStatement::acquire() -I- */
void SAL_CALL OStatement::acquire()
	throw()
{
	OSL_TRACE("OStatement::acquire");
	OCommonStatement::acquire();
}
/* }}} */


/* {{{ OStatement::release() -I- */
void SAL_CALL OStatement::release()
	throw()
{
	OSL_TRACE("OStatement::release");
	OCommonStatement::release();
}
/* }}} */


/* {{{ OCommonStatement::getPropertySetInfo() -I- */
Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OCommonStatement::getPropertySetInfo()
	throw(RuntimeException)
{
	OSL_TRACE("OCommonStatement::getPropertySetInfo");
	return(::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()));
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
