/************************************************************** * * 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 #include #include #include "odbc/OPreparedStatement.hxx" #include "odbc/OBoundParam.hxx" #include #include "odbc/OTools.hxx" #include "odbc/ODriver.hxx" #include "odbc/OResultSet.hxx" #include "odbc/OResultSetMetaData.hxx" #include #include #include #include "connectivity/dbtools.hxx" #include #include "connectivity/FValue.hxx" #include "resource/common_res.hrc" #include "connectivity/sqlparse.hxx" using namespace ::comphelper; using namespace connectivity; using namespace connectivity::odbc; 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; IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement"); OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const ::rtl::OUString& sql) :OStatement_BASE2(_pConnection) ,numParams(0) ,boundParams(NULL) ,m_bPrepared(sal_False) { m_sSqlStatement = sql; try { if(_pConnection->isParameterSubstitutionEnabled()) { OSQLParser aParser(_pConnection->getDriver()->getORB()); ::rtl::OUString sErrorMessage; ::rtl::OUString sNewSql; ::std::auto_ptr pNode( aParser.parseTree(sErrorMessage,sql) ); if ( pNode.get() ) { // special handling for parameters OSQLParseNode::substituteParameterNames(pNode.get()); pNode->parseNodeToStr( sNewSql, _pConnection ); m_sSqlStatement = sNewSql; } } } catch(Exception&) { } } // ----------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::acquire() throw() { OStatement_BASE2::acquire(); } // ----------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::release() throw() { OStatement_BASE2::release(); } // ----------------------------------------------------------------------------- Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException) { Any aRet = OStatement_BASE2::queryInterface(rType); return aRet.hasValue() ? aRet : OPreparedStatement_BASE::queryInterface(rType); } // ------------------------------------------------------------------------- ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException) { return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes()); } // ------------------------------------------------------------------------- Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); prepareStatement(); OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); if(!m_xMetaData.is()) m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle); return m_xMetaData; } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); // Close/clear our result set clearMyResultSet (); // Reset last warning message try { clearWarnings (); OStatement_BASE2::close(); FreeParams(); } catch (SQLException &) { // If we get an error, ignore } // Remove this Statement object from the Connection object's // list } // ------------------------------------------------------------------------- sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); sal_Bool needData = sal_False; // Reset warnings clearWarnings (); // Reset the statement handle, warning and saved Resultset reset(); // Call SQLExecute prepareStatement(); OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); try { SQLRETURN nReturn = N3SQLExecute(m_aStatementHandle); OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this); needData = nReturn == SQL_NEED_DATA; // Now loop while more data is needed (i.e. a data-at- // execution parameter was given). For each parameter // that needs data, put the data from the input stream. while (needData) { // Get the parameter number that requires data sal_Int32* paramIndex = 0; nReturn = N3SQLParamData(m_aStatementHandle,(SQLPOINTER*)¶mIndex); // If the parameter index is -1, there is no // more data required if ( !paramIndex || ( *paramIndex == -1 ) ) needData = sal_False; else { // Now we have the proper parameter // index, get the data from the input // stream and do a SQLPutData putParamData (*paramIndex); } } } catch (const SQLWarning&) { } // Now loop while more data is needed (i.e. a data-at- // execution parameter was given). For each parameter // that needs data, put the data from the input stream. while (needData) { // Get the parameter number that requires data sal_Int32* paramIndex = 0; N3SQLParamData (m_aStatementHandle,(SQLPOINTER*)¶mIndex); // If the parameter index is -1, there is no more // data required if (*paramIndex == -1) { needData = sal_False; } else { // Now we have the proper parameter index, // get the data from the input stream // and do a SQLPutData putParamData(*paramIndex); } } // Now determine if there is a result set associated with // the SQL statement that was executed. Get the column // count, and if it is not zero, there is a result set. return getColumnCount() > 0; } // ------------------------------------------------------------------------- sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); sal_Int32 numRows = -1; prepareStatement(); // Execute the statement. If execute returns sal_False, a // row count exists. if (!execute()) numRows = getUpdateCount (); else { // No update count was produced (a ResultSet was). Raise // an exception m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this); } return numRows; } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) { ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding())); setParameter(parameterIndex,DataType::CHAR,aString.getLength(),(void*)&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); Reference< XResultSet > rs = NULL; prepareStatement(); if (execute()) rs = getResultSet(sal_False); else { // No ResultSet was produced. Raise an exception m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this); } return rs; } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); sal_Int32 value = 0; // If the parameter is sal_True, set the value to 1 if (x) { value = 1; } // Set the parameter as if it were an integer setInt (parameterIndex, value); } // ------------------------------------------------------------------------- void OPreparedStatement::setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void* _pData) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); prepareStatement(); // Allocate a buffer to be used in binding. This will be // a 'permanent' buffer that the bridge will fill in with // the bound data in native format. checkParameterIndex(parameterIndex); sal_Int32 nRealSize = _nSize; SQLSMALLINT fSqlType = static_cast(OTools::jdbcTypeToOdbc(_nType)); switch(fSqlType) { case SQL_CHAR: case SQL_VARCHAR: case SQL_DECIMAL: case SQL_NUMERIC: ++nRealSize; break; case SQL_BINARY: case SQL_VARBINARY: nRealSize=1; //dummy buffer, binary data isn't copied break; default: break; } sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize); OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); OTools::bindParameter( m_pConnection, m_aStatementHandle, parameterIndex, bindBuf, getLengthBuf(parameterIndex), fSqlType, sal_False, m_pConnection->useOldDateFormat(), _pData, (Reference )*this, getOwnConnection()->getTextEncoding()); } // ----------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,DataType::TINYINT,sizeof(sal_Int8),&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException) { DATE_STRUCT x = OTools::DateToOdbcDate(aData); setParameter(parameterIndex,DataType::DATE,sizeof(DATE_STRUCT),&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException) { TIME_STRUCT x = OTools::TimeToOdbcTime(aVal); setParameter(parameterIndex,DataType::TIME,sizeof(TIME_STRUCT),&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException) { TIMESTAMP_STRUCT x = OTools::DateTimeToTimestamp(aVal); setParameter(parameterIndex,DataType::TIMESTAMP,sizeof(TIMESTAMP_STRUCT),&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,DataType::DOUBLE,sizeof(double),&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,DataType::FLOAT,sizeof(float),&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,DataType::INTEGER,sizeof(sal_Int32),&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException) { try { setParameter(parameterIndex,DataType::BIGINT,sizeof(sal_Int64),&x); } catch(SQLException&) { setString(parameterIndex,ORowSetValue(x)); } } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); prepareStatement(); // Get the buffer needed for the length checkParameterIndex(parameterIndex); sal_Int8* lenBuf = getLengthBuf (parameterIndex); *(SQLLEN*)lenBuf = SQL_NULL_DATA; SQLLEN prec = 0; SQLULEN nColumnSize = 0; if (sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR) { prec = 1; nColumnSize = 1; } SQLSMALLINT fCType = 0; SQLSMALLINT fSqlType = 0; SQLSMALLINT nDecimalDigits = 0; OTools::getBindTypes( sal_False, m_pConnection->useOldDateFormat(), (SQLSMALLINT)sqlType, fCType, fSqlType); SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle, (SQLUSMALLINT)parameterIndex, (SQLSMALLINT)SQL_PARAM_INPUT, fCType, fSqlType, nColumnSize, nDecimalDigits, NULL, prec, (SQLLEN*)lenBuf ); OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException) { if ( x.is() ) setStream(parameterIndex, x->getCharacterStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException) { if ( x.is() ) setStream(parameterIndex, x->getBinaryStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException) { ::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this ); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException) { ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this ); } // ------------------------------------------------------------------------- void OPreparedStatement::setDecimal( sal_Int32 parameterIndex, const ::rtl::OUString& x ) { ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding())); setParameter(parameterIndex,DataType::DECIMAL,aString.getLength(),(void*)&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) { checkDisposed(OStatement_BASE::rBHelper.bDisposed); ::osl::MutexGuard aGuard( m_aMutex ); prepareStatement(); // For each known SQL Type, call the appropriate // set routine switch (sqlType) { case DataType::VARCHAR: case DataType::LONGVARCHAR: if(x.hasValue()) { ::rtl::OUString sStr; x >>= sStr; ::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding())); setParameter(parameterIndex,sqlType,aString.getLength(),&aString); } else setNull(parameterIndex,sqlType); break; case DataType::DECIMAL: { ORowSetValue aValue; aValue.fill(x); setDecimal(parameterIndex,aValue); } break; case DataType::NUMERIC: { ORowSetValue aValue; aValue.fill(x); setString(parameterIndex,aValue); } break; default: ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale); } } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); setNull(parameterIndex,sqlType); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) { if (!::dbtools::implSetObject(this, parameterIndex, x)) { // there is no other setXXX call which can handle the value in x throw SQLException(); } } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,DataType::SMALLINT,sizeof(sal_Int16),&x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) { setParameter(parameterIndex,DataType::BINARY,x.getLength(),(void*)&x); boundParams[parameterIndex-1].setSequence(x); // this assures that the sequence stays alive } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) { setStream(parameterIndex, x, length, DataType::LONGVARCHAR); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) { setStream(parameterIndex, x, length, DataType::LONGVARBINARY); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) { prepareStatement(); OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS); nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND); } // ------------------------------------------------------------------------- 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 > (); } // ------------------------------------------------------------------------- //==================================================================== // methods //==================================================================== //-------------------------------------------------------------------- // initBoundParam // Initialize the bound parameter objects //-------------------------------------------------------------------- void OPreparedStatement::initBoundParam () throw(SQLException) { OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); // Get the number of parameters numParams = 0; N3SQLNumParams (m_aStatementHandle,&numParams); // There are parameter markers, allocate the bound // parameter objects if (numParams > 0) { // Allocate an array of bound parameter objects boundParams = new OBoundParam[numParams]; // Allocate and initialize each bound parameter for (sal_Int32 i = 0; i < numParams; i++) { boundParams[i] = OBoundParam(); boundParams[i].initialize (); } } } // ------------------------------------------------------------------------- //-------------------------------------------------------------------- // allocBindBuf // Allocate storage for the permanent data buffer for the bound // parameter. //-------------------------------------------------------------------- sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen) { sal_Int8* b = NULL; // Sanity check the parameter number if ((index >= 1) && (index <= numParams) && bufLen > 0 ) { b = boundParams[index - 1].allocBindDataBuffer(bufLen); } return b; } // ------------------------------------------------------------------------- //-------------------------------------------------------------------- // getDataBuf // Gets the data buffer for the given parameter index //-------------------------------------------------------------------- sal_Int8* OPreparedStatement::getDataBuf (sal_Int32 index) { sal_Int8* b = NULL; // Sanity check the parameter number if ((index >= 1) && (index <= numParams)) { b = boundParams[index - 1].getBindDataBuffer (); } return b; } // ------------------------------------------------------------------------- //-------------------------------------------------------------------- // getLengthBuf // Gets the length buffer for the given parameter index //-------------------------------------------------------------------- sal_Int8* OPreparedStatement::getLengthBuf (sal_Int32 index) { sal_Int8* b = NULL; // Sanity check the parameter number if ((index >= 1) && (index <= numParams)) { b = boundParams[index - 1].getBindLengthBuffer (); } return b; } // ------------------------------------------------------------------------- //-------------------------------------------------------------------- // getParamLength // Returns the length of the given parameter number. When each // parameter was bound, a 4-sal_Int8 buffer was given to hold the // length (stored in native format). Get the buffer, convert the // buffer from native format, and return it. If the length is -1, // the column is considered to be NULL. //-------------------------------------------------------------------- sal_Int32 OPreparedStatement::getParamLength ( sal_Int32 index) { sal_Int32 paramLen = SQL_NULL_DATA; // Sanity check the parameter number if ((index >= 1) && (index <= numParams)) { // Now get the length of the parameter from the // bound param array. -1 is returned if it is NULL. long n = 0; memcpy (&n, boundParams[index -1].getBindLengthBuffer (), sizeof (n)); paramLen = n; } return paramLen; } // ------------------------------------------------------------------------- //-------------------------------------------------------------------- // putParamData // Puts parameter data from a previously bound input stream. The // input stream was bound using SQL_LEN_DATA_AT_EXEC. //-------------------------------------------------------------------- void OPreparedStatement::putParamData (sal_Int32 index) throw(SQLException) { // Sanity check the parameter index if ((index < 1) || (index > numParams)) { return; } // We'll transfer up to MAX_PUT_DATA_LENGTH at a time Sequence< sal_Int8 > buf( MAX_PUT_DATA_LENGTH ); // Get the information about the input stream Reference< XInputStream> inputStream = boundParams[index - 1].getInputStream (); if ( !inputStream.is() ) { ::connectivity::SharedResources aResources; const ::rtl::OUString sError( aResources.getResourceString(STR_NO_INPUTSTREAM)); throw SQLException (sError, *this,::rtl::OUString(),0,Any()); } sal_Int32 maxBytesLeft = boundParams[index - 1].getInputStreamLen (); // Loop while more data from the input stream sal_Int32 haveRead = 0; try { do { sal_Int32 toReadThisRound = ::std::min( MAX_PUT_DATA_LENGTH, maxBytesLeft ); // Read some data from the input stream haveRead = inputStream->readBytes( buf, toReadThisRound ); OSL_ENSURE( haveRead == buf.getLength(), "OPreparedStatement::putParamData: inconsistency!" ); if ( !haveRead ) // no more data in the stream - the given stream length was a maximum which could not be // fulfilled by the stream break; // Put the data OSL_ENSURE( m_aStatementHandle, "OPreparedStatement::putParamData: StatementHandle is null!" ); N3SQLPutData ( m_aStatementHandle, buf.getArray(), buf.getLength() ); // decrement the number of bytes still needed maxBytesLeft -= haveRead; } while ( maxBytesLeft > 0 ); } catch (const IOException& ex) { // If an I/O exception was generated, turn // it into a SQLException throw SQLException(ex.Message,*this,::rtl::OUString(),0,Any()); } } // ------------------------------------------------------------------------- //-------------------------------------------------------------------- // getPrecision // Given a SQL type, return the maximum precision for the column. // Returns -1 if not known //-------------------------------------------------------------------- sal_Int32 OPreparedStatement::getPrecision ( sal_Int32 sqlType) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); sal_Int32 prec = -1; const TTypeInfoVector& rTypeInfo = m_pConnection->getTypeInfo(); if ( !rTypeInfo.empty() ) { m_pConnection->buildTypeInfo(); } if ( !rTypeInfo.empty() ) { OTypeInfo aInfo; aInfo.nType = (sal_Int16)sqlType; TTypeInfoVector::const_iterator aIter = ::std::find(rTypeInfo.begin(),rTypeInfo.end(),aInfo); if(aIter != rTypeInfo.end()) prec = (*aIter).nPrecision; } return prec; } //-------------------------------------------------------------------- // setStream // Sets an input stream as a parameter, using the given SQL type //-------------------------------------------------------------------- void OPreparedStatement::setStream( sal_Int32 ParameterIndex, const Reference< XInputStream>& x, SQLLEN length, sal_Int32 SQLtype) throw(SQLException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatement_BASE::rBHelper.bDisposed); prepareStatement(); checkParameterIndex(ParameterIndex); // Get the buffer needed for the length sal_Int8* lenBuf = getLengthBuf(ParameterIndex); // Allocate a new buffer for the parameter data. This buffer // will be returned by SQLParamData (it is set to the parameter // number, a 4-sal_Int8 integer) sal_Int8* dataBuf = allocBindBuf (ParameterIndex, 4); // Bind the parameter with SQL_LEN_DATA_AT_EXEC SQLSMALLINT Ctype = SQL_C_CHAR; SQLLEN atExec = SQL_LEN_DATA_AT_EXEC (length); memcpy (dataBuf, &ParameterIndex, sizeof(ParameterIndex)); memcpy (lenBuf, &atExec, sizeof (atExec)); if ((SQLtype == SQL_BINARY) || (SQLtype == SQL_VARBINARY) || (SQLtype == SQL_LONGVARBINARY)) Ctype = SQL_C_BINARY; OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); N3SQLBindParameter(m_aStatementHandle, (SQLUSMALLINT)ParameterIndex, (SQLUSMALLINT)SQL_PARAM_INPUT, Ctype, (SQLSMALLINT)SQLtype, (SQLULEN)length, 0, dataBuf, sizeof(ParameterIndex), (SQLLEN*)lenBuf); // Save the input stream boundParams[ParameterIndex - 1].setInputStream (x, length); } // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- void OPreparedStatement::FreeParams() { numParams = 0; delete [] boundParams; boundParams = NULL; } // ------------------------------------------------------------------------- void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception) { try { switch(nHandle) { case PROPERTY_ID_RESULTSETCONCURRENCY: if(!isPrepared()) setResultSetConcurrency(comphelper::getINT32(rValue)); break; case PROPERTY_ID_RESULTSETTYPE: if(!isPrepared()) setResultSetType(comphelper::getINT32(rValue)); break; case PROPERTY_ID_FETCHDIRECTION: if(!isPrepared()) setFetchDirection(comphelper::getINT32(rValue)); break; case PROPERTY_ID_USEBOOKMARKS: if(!isPrepared()) setUsingBookmarks(comphelper::getBOOL(rValue)); break; default: OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue); } } catch(const SQLException&) { // throw Exception(e.Message,*this); } } // ----------------------------------------------------------------------------- void OPreparedStatement::prepareStatement() { if(!isPrepared()) { OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); ::rtl::OString aSql(::rtl::OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding())); SQLRETURN nReturn = N3SQLPrepare(m_aStatementHandle,(SDB_ODBC_CHAR *) aSql.getStr(),aSql.getLength()); OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this); m_bPrepared = sal_True; initBoundParam(); } } // ----------------------------------------------------------------------------- void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex) { if( !_parameterIndex || _parameterIndex > numParams) { ::connectivity::SharedResources aResources; const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX, "$pos$", ::rtl::OUString::valueOf(_parameterIndex), "$count$", ::rtl::OUString::valueOf((sal_Int32)numParams) )); SQLException aNext(sError,*this, ::rtl::OUString(),0,Any()); ::dbtools::throwInvalidIndexException(*this,makeAny(aNext)); } } // ----------------------------------------------------------------------------- OResultSet* OPreparedStatement::createResulSet() { OResultSet* pReturn = new OResultSet(m_aStatementHandle,this); pReturn->setMetaData(getMetaData()); return pReturn; } // -----------------------------------------------------------------------------