/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * The Contents of this file are made available subject to the terms of * the BSD license. * * Copyright 2000, 2010 Oracle and/or its affiliates. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *************************************************************************/ #include "FConnection.hxx" #include "FPreparedStatement.hxx" #include "FResultSetMetaData.hxx" #include "FResultSet.hxx" #include "Util.hxx" #include #include #include #include #include #include using namespace connectivity::firebird; using namespace ::comphelper; using namespace ::osl; using namespace com::sun::star; 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::container; using namespace com::sun::star::io; using namespace com::sun::star::util; typedef struct vary { short vary_length; char vary_string[1]; } VARY; IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.firebird.PreparedStatement","com.sun.star.sdbc.PreparedStatement"); OPreparedStatement::OPreparedStatement( OConnection* _pConnection, const TTypeInfoVector& _TypeInfo, const OUString& sql) :OStatementCommonBase(_pConnection) ,m_aTypeInfo(_TypeInfo) ,m_sSqlStatement(sql) ,m_statementHandle(0) ,m_pOutSqlda(0) ,m_pInSqlda(0) { SAL_INFO("connectivity.firebird", "OPreparedStatement(). " "sql: " << sql); } void OPreparedStatement::ensurePrepared() throw (SQLException) { MutexGuard aGuard(m_pConnection->getMutex()); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); if (m_statementHandle) return; ISC_STATUS aErr = 0; if (!m_pInSqlda) { m_pInSqlda = (XSQLDA*) malloc(XSQLDA_LENGTH(10)); m_pInSqlda->version = SQLDA_VERSION1; m_pInSqlda->sqln = 10; } // TODO: free this on closing aErr = prepareAndDescribeStatement(m_sSqlStatement, m_statementHandle, m_pOutSqlda, m_pInSqlda); if (aErr) { SAL_WARN("connectivity.firebird", "prepareAndDescribeStatement failed"); } else if (m_statementHandle) { isc_dsql_describe_bind(m_statusVector, &m_statementHandle, 1, m_pInSqlda); } if (aErr) { SAL_WARN("connectivity.firebird", "isc_dsql_describe_bind failed"); } else if (m_pInSqlda->sqld > m_pInSqlda->sqln) // Not large enough { short nItems = m_pInSqlda->sqld; free(m_pInSqlda); m_pInSqlda = (XSQLDA*) malloc(XSQLDA_LENGTH(nItems)); m_pInSqlda->version = SQLDA_VERSION1; m_pInSqlda->sqln = nItems; isc_dsql_describe_bind(m_statusVector, &m_statementHandle, 1, m_pInSqlda); } // char aItems[] = { // isc_info_sql_num_variables // }; // char aResultBuffer[8]; // isc_dsql_sql_info(m_statusVector, // &m_statementHandle, // sizeof(aItems), // aItems, // sizeof(aResultBuffer), // aResultBuffer); // if (aResultBuffer[0] == isc_info_sql_num_variables) // { // short aVarLength = (short) isc_vax_integer(aResultBuffer+1, 2); // m_nNumParams = isc_vax_integer(aResultBuffer+3, aVarLength); // } // } mallocSQLVAR(m_pInSqlda); OConnection::evaluateStatusVector(m_statusVector, m_sSqlStatement, *this); } OPreparedStatement::~OPreparedStatement() { } void SAL_CALL OPreparedStatement::acquire() throw() { OStatementCommonBase::acquire(); } void SAL_CALL OPreparedStatement::release() throw() { OStatementCommonBase::release(); } Any SAL_CALL OPreparedStatement::queryInterface(const Type& rType) throw(RuntimeException) { Any aRet = OStatementCommonBase::queryInterface(rType); if(!aRet.hasValue()) aRet = OPreparedStatement_Base::queryInterface(rType); return aRet; } uno::Sequence< Type > SAL_CALL OPreparedStatement::getTypes() throw(RuntimeException) { return concatSequences(OPreparedStatement_Base::getTypes(), OStatementCommonBase::getTypes()); } Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData() throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); // TODO: implement // if(!m_xMetaData.is()) // m_xMetaData = new OResultSetMetaData(m_pConnection, m_pSqlda); // TODO: uncomment once PreparedStatement reimplemented with SQLDA return m_xMetaData; } void SAL_CALL OPreparedStatement::close() throw(SQLException, RuntimeException) { SAL_INFO("connectivity.firebird", "close()"); MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); if (m_statementHandle) { // TODO: implement } OStatementCommonBase::close(); } sal_Bool SAL_CALL OPreparedStatement::execute() throw(SQLException, RuntimeException) { MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); // TODO: implement return sal_False; } sal_Int32 SAL_CALL OPreparedStatement::executeUpdate() throw(SQLException, RuntimeException) { MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); // TODO: implement return 0; } void SAL_CALL OPreparedStatement::setString(sal_Int32 nParameterIndex, const OUString& x) throw(SQLException, RuntimeException) { SAL_INFO("connectivity.firebird", "setString(). " "parameterIndex: " << nParameterIndex << " , " "x: " << x); MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); ensurePrepared(); checkParameterIndex(nParameterIndex); OString str = OUStringToOString(x , RTL_TEXTENCODING_UTF8 ); XSQLVAR* pVar = m_pOutSqlda->sqlvar + (nParameterIndex - 1); int dtype = (pVar->sqltype & ~1); // drop flag bit for now switch (dtype) { case SQL_VARYING: pVar->sqltype = SQL_TEXT; case SQL_TEXT: if (str.getLength() > pVar->sqllen) { // Cut off overflow memcpy(pVar->sqldata, str.getStr(), pVar->sqllen); } else { memcpy(pVar->sqldata, str.getStr(), str.getLength()); // Fill remainder with spaces // TODO: would 0 be better here for filling? memset(pVar->sqldata + str.getLength(), ' ', pVar->sqllen - str.getLength()); } break; default: // TODO: sane error message throw SQLException(); } } Reference< XConnection > SAL_CALL OPreparedStatement::getConnection() throw(SQLException, RuntimeException) { MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); return Reference< XConnection >(m_pConnection); } Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery() throw(SQLException, RuntimeException) { SAL_INFO("connectivity.firebird", "executeQuery(). " "Got called with sql: " << m_sSqlStatement); MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); ensurePrepared(); ISC_STATUS aErr; aErr = isc_dsql_execute(m_statusVector, &m_pConnection->getTransaction(), &m_statementHandle, 1, m_pInSqlda); if (aErr) { SAL_WARN("connectivity.firebird", "isc_dsql_execute failed" ); OConnection::evaluateStatusVector(m_statusVector, "isc_dsql_execute", *this); } uno::Reference< OResultSet > pResult(new OResultSet(m_pConnection, uno::Reference< XInterface >(*this), m_statementHandle, m_pOutSqlda)); m_xResultSet = pResult.get(); return m_xResultSet; } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) aData; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) aVal; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) aVal; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 aVal ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) aVal; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) sqlType; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setArray( sal_Int32 parameterIndex, const Reference< XArray >& x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setRef( sal_Int32 parameterIndex, const Reference< XRef >& x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; (void) sqlType; (void) scale; checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) sqlType; (void) typeName; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; (void) length; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) { (void) parameterIndex; (void) x; (void) length; ::osl::MutexGuard aGuard( m_pConnection->getMutex() ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) { } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException) { } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException) { } // ------------------------------------------------------------------------- Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException) { return Sequence< sal_Int32 > (); } // ------------------------------------------------------------------------- void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception) { switch(nHandle) { case PROPERTY_ID_RESULTSETCONCURRENCY: break; case PROPERTY_ID_RESULTSETTYPE: break; case PROPERTY_ID_FETCHDIRECTION: break; case PROPERTY_ID_USEBOOKMARKS: break; default: OStatementCommonBase::setFastPropertyValue_NoBroadcast(nHandle,rValue); } } void OPreparedStatement::checkParameterIndex(sal_Int32 nParameterIndex) throw(SQLException) { ensurePrepared(); if ((nParameterIndex == 0) || (nParameterIndex > m_pOutSqlda->sqld)) throw SQLException(); // TODO: sane error message here. } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */