/************************************************************** * * 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. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_connectivity.hxx" #include "connectivity/sqlparse.hxx" #include "ado/APreparedStatement.hxx" #include #include "ado/AResultSetMetaData.hxx" #include "ado/AResultSet.hxx" #include "ado/ADriver.hxx" #include #include #include #include "connectivity/dbexception.hxx" #include "connectivity/dbtools.hxx" #include "resource/ado_res.hrc" #include #define CHECK_RETURN(x) \ if(!x) \ ADOS::ThrowException(*m_pConnection->getConnection(),*this); #ifdef max # undef max #endif //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ using namespace connectivity::ado; using namespace connectivity; 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::util; IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement"); OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OTypeInfoMap& _TypeInfo,const ::rtl::OUString& sql) : OStatement_Base( _pConnection ) ,m_aTypeInfo(_TypeInfo) { osl_incrementInterlockedCount( &m_refCount ); OSQLParser aParser(_pConnection->getDriver()->getORB()); ::rtl::OUString sErrorMessage; ::rtl::OUString sNewSql; OSQLParseNode* pNode = aParser.parseTree(sErrorMessage,sql); if(pNode) { // special handling for parameters /* we recusive replace all occurences of ? in the statement and replace them with name like "æ¬å" */ sal_Int32 nParameterCount = 0; ::rtl::OUString sDefaultName = ::rtl::OUString::createFromAscii("parame"); replaceParameterNodeName(pNode,sDefaultName,nParameterCount); pNode->parseNodeToStr( sNewSql, _pConnection ); delete pNode; } else sNewSql = sql; CHECK_RETURN(m_Command.put_CommandText(sNewSql)) CHECK_RETURN(m_Command.put_Prepared(VARIANT_TRUE)) m_pParameters = m_Command.get_Parameters(); m_pParameters->AddRef(); m_pParameters->Refresh(); osl_decrementInterlockedCount( &m_refCount ); } // ------------------------------------------------------------------------- OPreparedStatement::~OPreparedStatement() { if (m_pParameters) { OSL_ENSURE( sal_False, "OPreparedStatement::~OPreparedStatement: not disposed!" ); m_pParameters->Release(); m_pParameters = NULL; } } // ------------------------------------------------------------------------- Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException) { Any aRet = OStatement_Base::queryInterface(rType); return aRet.hasValue() ? aRet : ::cppu::queryInterface( rType, static_cast< XPreparedStatement*>(this), static_cast< XParameters*>(this), static_cast< XPreparedBatchExecution*>(this), static_cast< XResultSetMetaDataSupplier*>(this)); } // ------------------------------------------------------------------------- ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException) { ::cppu::OTypeCollection aTypes( ::getCppuType( (const ::com::sun::star::uno::Reference< XPreparedStatement > *)0 ), ::getCppuType( (const ::com::sun::star::uno::Reference< XParameters > *)0 ), ::getCppuType( (const ::com::sun::star::uno::Reference< XResultSetMetaDataSupplier > *)0 ), ::getCppuType( (const ::com::sun::star::uno::Reference< XPreparedBatchExecution > *)0 )); return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_Base::getTypes()); } // ------------------------------------------------------------------------- Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException) { if(!m_xMetaData.is() && m_RecordSet.IsValid()) m_xMetaData = new OResultSetMetaData(m_RecordSet); return m_xMetaData; } // ------------------------------------------------------------------------- void OPreparedStatement::disposing() { m_xMetaData.clear(); if (m_pParameters) { m_pParameters->Release(); m_pParameters = NULL; } OStatement_Base::disposing(); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException) { { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); } dispose(); } // ------------------------------------------------------------------------- sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); SQLWarning warning; // Reset warnings clearWarnings (); // Reset the statement handle, warning and saved Resultset // reset(); // Call SQLExecute try { ADORecordset* pSet=NULL; CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet)) m_RecordSet = WpADORecordset(pSet); } catch (SQLWarning& ex) { // Save pointer to warning and save with ResultSet // object once it is created. warning = ex; } return m_RecordSet.IsValid(); } // ------------------------------------------------------------------------- sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); ADORecordset* pSet=NULL; CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet)) if ( VT_ERROR == m_RecordsAffected.getType() ) { ADOS::ThrowException(*m_pConnection->getConnection(),*this); // to be sure that we get the error really thrown throw SQLException(); } m_RecordSet = WpADORecordset(pSet); return static_cast(m_RecordsAffected); } // ------------------------------------------------------------------------- void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const DataTypeEnum& _eType, const sal_Int32& _nSize,const OLEVariant& _Val) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); sal_Int32 nCount = 0; m_pParameters->get_Count(&nCount); if(nCount < (parameterIndex-1)) { ::rtl::OUString sDefaultName = ::rtl::OUString::createFromAscii("parame"); sDefaultName += ::rtl::OUString::valueOf(parameterIndex); ADOParameter* pParam = m_Command.CreateParameter(sDefaultName,_eType,adParamInput,_nSize,_Val); if(pParam) { m_pParameters->Append(pParam); #if OSL_DEBUG_LEVEL > 0 ADOParameter* pParam = NULL; m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam); WpADOParameter aParam(pParam); if(pParam) { DataTypeEnum eType = aParam.GetADOType(); (void)eType; } #endif } } else { ADOParameter* pParam = NULL; m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam); WpADOParameter aParam(pParam); if(pParam) { #if OSL_DEBUG_LEVEL > 0 ::rtl::OUString sParam = aParam.GetName(); #endif // OSL_DEBUG_LEVEL DataTypeEnum eType = aParam.GetADOType(); if ( _eType != eType && _eType != adDBTimeStamp ) { aParam.put_Type(_eType); eType = _eType; aParam.put_Size(_nSize); } if ( adVarBinary == eType && aParam.GetAttributes() == adParamLong ) { aParam.AppendChunk(_Val); } else CHECK_RETURN(aParam.PutValue(_Val)); } } ADOS::ThrowException(*m_pConnection->getConnection(),*this); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) { setParameter( parameterIndex, adLongVarWChar, ::std::numeric_limits< sal_Int32 >::max(), x ); } // ------------------------------------------------------------------------- Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); return (Reference< XConnection >)m_pConnection; } // ------------------------------------------------------------------------- Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); // first clear the old things m_xMetaData.clear(); disposeResultSet(); if(m_RecordSet.IsValid()) m_RecordSet.Close(); m_RecordSet.clear(); // the create the new onces m_RecordSet.Create(); OLEVariant aCmd; aCmd.setIDispatch(m_Command); OLEVariant aCon; aCon.setNoArg(); CHECK_RETURN(m_RecordSet.put_CacheSize(m_nFetchSize)) CHECK_RETURN(m_RecordSet.put_MaxRecords(m_nMaxRows)) CHECK_RETURN(m_RecordSet.Open(aCmd,aCon,m_eCursorType,m_eLockType,adOpenUnspecified)) CHECK_RETURN(m_RecordSet.get_CacheSize(m_nFetchSize)) CHECK_RETURN(m_RecordSet.get_MaxRecords(m_nMaxRows)) CHECK_RETURN(m_RecordSet.get_CursorType(m_eCursorType)) CHECK_RETURN(m_RecordSet.get_LockType(m_eLockType)) OResultSet* pSet = new OResultSet(m_RecordSet,this); Reference< XResultSet > xRs = pSet; pSet->construct(); pSet->setMetaData(getMetaData()); m_xResultSet = WeakReference(xRs); return xRs; } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adBoolean,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adTinyInt,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adDBDate,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adDBTime,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adDBTimeStamp,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adDouble,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adSingle,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adInteger,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adBigInt,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException) { OLEVariant aVal; aVal.setNull(); setParameter(parameterIndex,adEmpty,0,aVal); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException) { ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setClob", *this ); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException) { ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setBlob", *this ); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException) { ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setArray", *this ); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException) { ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setRef", *this ); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) { switch(sqlType) { case DataType::DECIMAL: case DataType::NUMERIC: setString(parameterIndex,::comphelper::getString(x)); break; default: ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale); break; } } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException) { setNull(parameterIndex,sqlType); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) { if(!::dbtools::implSetObject(this,parameterIndex,x)) { const ::rtl::OUString sError( m_pConnection->getResources().getResourceStringWithSubstitution( STR_UNKNOWN_PARA_TYPE, "$position$", ::rtl::OUString::valueOf(parameterIndex) ) ); ::dbtools::throwGenericSQLException(sError,*this); } // setObject (parameterIndex, x, sqlType, 0); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adSmallInt,sizeof(x),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,adVarBinary,sizeof(sal_Int8)*x.getLength(),x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< ::com::sun::star::io::XInputStream >& /*x*/, sal_Int32 /*length*/ ) throw(SQLException, RuntimeException) { ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this ); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) { if(x.is()) { Sequence< sal_Int8 > aData; x->readBytes(aData,length); setBytes(parameterIndex,aData); } } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); if(m_pParameters) { sal_Int32 nCount = 0; m_pParameters->get_Count(&nCount); OLEVariant aVal; aVal.setEmpty(); for(sal_Int32 i=0;iget_Item(OLEVariant(i),&pParam); WpADOParameter aParam(pParam); if(pParam) { ::rtl::OUString sParam = aParam.GetName(); CHECK_RETURN(aParam.PutValue(aVal)); } } // m_pParameters->Delete(OLEVariant(i)); } } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException) { // clearParameters( ); // m_aBatchList.erase(); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException) { } // ------------------------------------------------------------------------- Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException) { return Sequence< sal_Int32 > (); } // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::acquire() throw() { OStatement_Base::acquire(); } // ----------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::release() throw() { OStatement_Base::release(); } // ----------------------------------------------------------------------------- void OPreparedStatement::replaceParameterNodeName(OSQLParseNode* _pNode, const ::rtl::OUString& _sDefaultName, sal_Int32& _rParameterCount) { sal_Int32 nCount = _pNode->count(); for(sal_Int32 i=0;i < nCount;++i) { OSQLParseNode* pChildNode = _pNode->getChild(i); if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() == 1) { OSQLParseNode* pNewNode = new OSQLParseNode(::rtl::OUString::createFromAscii(":") ,SQL_NODE_PUNCTUATION,0); delete pChildNode->replace(pChildNode->getChild(0),pNewNode); ::rtl::OUString sParameterName = _sDefaultName; sParameterName += ::rtl::OUString::valueOf(++_rParameterCount); pChildNode->append(new OSQLParseNode( sParameterName,SQL_NODE_NAME,0)); } else replaceParameterNodeName(pChildNode,_sDefaultName,_rParameterCount); } } // -----------------------------------------------------------------------------