| /************************************************************** |
| * |
| * 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 <stdio.h> |
| #include <string.h> |
| #include <osl/diagnose.h> |
| #include "odbc/OPreparedStatement.hxx" |
| #include "odbc/OBoundParam.hxx" |
| #include <com/sun/star/sdbc/DataType.hpp> |
| #include "odbc/OTools.hxx" |
| #include "odbc/ODriver.hxx" |
| #include "odbc/OResultSet.hxx" |
| #include "odbc/OResultSetMetaData.hxx" |
| #include <cppuhelper/typeprovider.hxx> |
| #include <comphelper/sequence.hxx> |
| #include <com/sun/star/lang/DisposedException.hpp> |
| #include "connectivity/dbtools.hxx" |
| #include <comphelper/types.hxx> |
| #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<OSQLParseNode> 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<SQLSMALLINT>(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 <XInterface>)*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; |
| } |
| // ----------------------------------------------------------------------------- |