887 lines
29 KiB
C++
887 lines
29 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* Effective License of whole file:
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
* Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* the GNU Lesser General Public License Version 2.1
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* Contributor(s): Joerg Budischewski
|
|
*
|
|
* All parts contributed on or after August 2011:
|
|
*
|
|
* Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License or as specified alternatively below. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* Major Contributor(s):
|
|
* [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* For minor contributions see the git repository.
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 3 or later (the "GPLv3+"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
|
|
* in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
|
|
* instead of those above.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include "pq_preparedstatement.hxx"
|
|
#include "pq_resultset.hxx"
|
|
#include "pq_tools.hxx"
|
|
#include "pq_statics.hxx"
|
|
#include "pq_statement.hxx"
|
|
|
|
#include <rtl/strbuf.hxx>
|
|
#include <rtl/ustrbuf.hxx>
|
|
|
|
|
|
#include <cppuhelper/typeprovider.hxx>
|
|
#include <cppuhelper/queryinterface.hxx>
|
|
|
|
#include <com/sun/star/beans/PropertyAttribute.hpp>
|
|
|
|
#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
|
|
#include <com/sun/star/sdbc/ResultSetType.hpp>
|
|
|
|
#include <string.h>
|
|
|
|
using osl::Mutex;
|
|
using osl::MutexGuard;
|
|
|
|
using rtl::OUString;
|
|
using rtl::OUStringToOString;
|
|
using rtl::OStringToOUString;
|
|
using rtl::OUStringBuffer;
|
|
using rtl::OStringBuffer;
|
|
using rtl::OString;
|
|
|
|
using com::sun::star::uno::Any;
|
|
using com::sun::star::uno::makeAny;
|
|
using com::sun::star::uno::Type;
|
|
using com::sun::star::uno::RuntimeException;
|
|
using com::sun::star::uno::Exception;
|
|
using com::sun::star::uno::Sequence;
|
|
using com::sun::star::uno::Reference;
|
|
using com::sun::star::uno::XInterface;
|
|
using com::sun::star::uno::UNO_QUERY;
|
|
|
|
using com::sun::star::lang::IllegalArgumentException;
|
|
|
|
using com::sun::star::sdbc::XWarningsSupplier;
|
|
using com::sun::star::sdbc::XCloseable;
|
|
using com::sun::star::sdbc::XPreparedStatement;
|
|
using com::sun::star::sdbc::XParameters;
|
|
using com::sun::star::sdbc::XResultSet;
|
|
using com::sun::star::sdbc::XRef;
|
|
using com::sun::star::sdbc::XBlob;
|
|
using com::sun::star::sdbc::XClob;
|
|
using com::sun::star::sdbc::XArray;
|
|
using com::sun::star::sdbc::XConnection;
|
|
using com::sun::star::sdbc::XGeneratedResultSet;
|
|
using com::sun::star::sdbc::SQLException;
|
|
|
|
using com::sun::star::beans::Property;
|
|
using com::sun::star::beans::XPropertySetInfo;
|
|
using com::sun::star::beans::XPropertySet;
|
|
using com::sun::star::beans::XMultiPropertySet;
|
|
using com::sun::star::beans::XFastPropertySet;
|
|
|
|
#define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
|
|
namespace pq_sdbc_driver
|
|
{
|
|
static ::cppu::IPropertyArrayHelper & getPreparedStatementPropertyArrayHelper()
|
|
{
|
|
static ::cppu::IPropertyArrayHelper *pArrayHelper;
|
|
if( ! pArrayHelper )
|
|
{
|
|
MutexGuard guard( Mutex::getGlobalMutex() );
|
|
if( ! pArrayHelper )
|
|
{
|
|
static Property aTable[] =
|
|
{
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("CursorName") ), 0,
|
|
::getCppuType( (OUString *)0) , 0 ),
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("EscapeProcessing") ), 1,
|
|
::getBooleanCppuType() , 0 ),
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("FetchDirection") ), 2,
|
|
::getCppuType( (sal_Int32 *)0) , 0 ),
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("FetchSize") ), 3,
|
|
::getCppuType( (sal_Int32 *)0) , 0 ),
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("MaxFieldSize") ), 4,
|
|
::getCppuType( (sal_Int32 *)0) , 0 ),
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("MaxRows") ), 5,
|
|
::getCppuType( (sal_Int32 *)0) , 0 ),
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("QueryTimeOut") ), 6,
|
|
::getCppuType( (sal_Int32 *)0) , 0 ),
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("ResultSetConcurrency") ), 7,
|
|
::getCppuType( (sal_Int32 *)0) , 0 ),
|
|
Property(
|
|
OUString( RTL_CONSTASCII_USTRINGPARAM("ResultSetType") ), 8,
|
|
::getCppuType( (sal_Int32 *)0) , 0 )
|
|
};
|
|
OSL_ASSERT( sizeof(aTable)/ sizeof(Property) == PREPARED_STATEMENT_SIZE );
|
|
static ::cppu::OPropertyArrayHelper arrayHelper( aTable, PREPARED_STATEMENT_SIZE, sal_True );
|
|
pArrayHelper = &arrayHelper;
|
|
}
|
|
}
|
|
return *pArrayHelper;
|
|
}
|
|
|
|
static bool isOperator( char c )
|
|
{
|
|
static const char * operators = "<>=()!/&%.,;";
|
|
|
|
const char * w = operators;
|
|
for( ; *w && *w != c ; w ++);
|
|
return *w != 0;
|
|
}
|
|
|
|
static bool isNamedParameterStart( const rtl::OString & o , int index )
|
|
{
|
|
return o[index] == ':' && (
|
|
isWhitespace( o[index-1] ) || isOperator(o[index-1]) );
|
|
}
|
|
|
|
static bool isQuoted( const rtl::OString & str )
|
|
{
|
|
return str[0] == '"' || str[0] == '\'';
|
|
}
|
|
|
|
PreparedStatement::PreparedStatement(
|
|
const ::rtl::Reference< RefCountedMutex > & refMutex,
|
|
const Reference< XConnection > & conn,
|
|
struct ConnectionSettings *pSettings,
|
|
const ::rtl::OString & stmt )
|
|
: OComponentHelper( refMutex->mutex ),
|
|
OPropertySetHelper( OComponentHelper::rBHelper ),
|
|
m_connection( conn ),
|
|
m_pSettings( pSettings ),
|
|
m_stmt( stmt ),
|
|
m_refMutex( refMutex ),
|
|
m_lastOidInserted( InvalidOid )
|
|
{
|
|
m_props[PREPARED_STATEMENT_QUERY_TIME_OUT] = makeAny( (sal_Int32)0 );
|
|
m_props[PREPARED_STATEMENT_MAX_ROWS] = makeAny( (sal_Int32)0 );
|
|
m_props[PREPARED_STATEMENT_RESULT_SET_CONCURRENCY] = makeAny(
|
|
com::sun::star::sdbc::ResultSetConcurrency::READ_ONLY );
|
|
m_props[PREPARED_STATEMENT_RESULT_SET_TYPE] = makeAny(
|
|
com::sun::star::sdbc::ResultSetType::SCROLL_INSENSITIVE );
|
|
|
|
splitSQL( m_stmt, m_splittedStatement );
|
|
int elements = 0;
|
|
for( int i = 0, max = m_splittedStatement.size(); i < max ; i ++ )
|
|
{
|
|
const OString &str = m_splittedStatement[i];
|
|
// ignore quoted strings ....
|
|
if( ! isQuoted( str ) )
|
|
{
|
|
// the ':' cannot be the first or the last part of the
|
|
// token,
|
|
// the ? cannot be the first part of the token , so we start
|
|
// at one
|
|
for( int index = 1 ; index < str.getLength() ; index ++ )
|
|
{
|
|
if( str[index] == '?' ||
|
|
isNamedParameterStart( str , index )
|
|
)
|
|
{
|
|
elements ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
m_vars = OStringVector ( elements );
|
|
}
|
|
|
|
PreparedStatement::~PreparedStatement()
|
|
{
|
|
POSTGRE_TRACE( "dtor PreparedStatement" );
|
|
}
|
|
|
|
void PreparedStatement::checkColumnIndex( sal_Int32 parameterIndex )
|
|
{
|
|
if( parameterIndex < 1 || parameterIndex > (sal_Int32) m_vars.size() )
|
|
{
|
|
OUStringBuffer buf( 128 );
|
|
buf.appendAscii( "pq_preparedstatement: parameter index out of range (expected 1 to " );
|
|
buf.append( (sal_Int32 ) m_vars.size() );
|
|
buf.appendAscii( ", got " );
|
|
buf.append( parameterIndex );
|
|
buf.appendAscii( ", statement '" );
|
|
buf.append( OStringToOUString( m_stmt, m_pSettings->encoding ) );
|
|
buf.appendAscii( "')" );
|
|
throw SQLException( buf.makeStringAndClear(), *this, OUString(), 1, Any () );
|
|
}
|
|
}
|
|
void PreparedStatement::checkClosed() throw (SQLException, RuntimeException )
|
|
{
|
|
if( ! m_pSettings || ! m_pSettings->pConnection )
|
|
throw SQLException(
|
|
ASCII_STR("pq_driver: PreparedStatement or connection has already been closed !" ),
|
|
*this, OUString(),1,Any());
|
|
}
|
|
|
|
Any PreparedStatement::queryInterface( const Type & reqType ) throw (RuntimeException)
|
|
{
|
|
Any ret;
|
|
|
|
ret = OComponentHelper::queryInterface( reqType );
|
|
if( ! ret.hasValue() )
|
|
ret = ::cppu::queryInterface( reqType,
|
|
static_cast< XWarningsSupplier * > ( this ),
|
|
static_cast< XPreparedStatement * > ( this ),
|
|
static_cast< com::sun::star::sdbc::XResultSetMetaDataSupplier * > ( this ),
|
|
static_cast< XParameters * > ( this ),
|
|
static_cast< XCloseable * > ( this ),
|
|
static_cast< XGeneratedResultSet * > ( this ),
|
|
static_cast< XPropertySet * > ( this ),
|
|
static_cast< XMultiPropertySet * > ( this ),
|
|
static_cast< XFastPropertySet * > ( this ) );
|
|
return ret;
|
|
}
|
|
|
|
|
|
Sequence< Type > PreparedStatement::getTypes() throw ( RuntimeException )
|
|
{
|
|
static cppu::OTypeCollection *pCollection;
|
|
if( ! pCollection )
|
|
{
|
|
MutexGuard guard( osl::Mutex::getGlobalMutex() );
|
|
if( !pCollection )
|
|
{
|
|
static cppu::OTypeCollection collection(
|
|
getCppuType( (Reference< XWarningsSupplier> *) 0 ),
|
|
getCppuType( (Reference< XPreparedStatement> *) 0 ),
|
|
getCppuType( (Reference< com::sun::star::sdbc::XResultSetMetaDataSupplier> *) 0 ),
|
|
getCppuType( (Reference< XParameters> *) 0 ),
|
|
getCppuType( (Reference< XCloseable> *) 0 ),
|
|
getCppuType( (Reference< XGeneratedResultSet> *) 0 ),
|
|
getCppuType( (Reference< XPropertySet >*) 0 ),
|
|
getCppuType( (Reference< XFastPropertySet > *) 0 ),
|
|
getCppuType( (Reference< XMultiPropertySet > *) 0 ),
|
|
OComponentHelper::getTypes());
|
|
pCollection = &collection;
|
|
}
|
|
}
|
|
return pCollection->getTypes();
|
|
}
|
|
|
|
Sequence< sal_Int8> PreparedStatement::getImplementationId() throw ( RuntimeException )
|
|
{
|
|
static cppu::OImplementationId *pId;
|
|
if( ! pId )
|
|
{
|
|
MutexGuard guard( osl::Mutex::getGlobalMutex() );
|
|
if( ! pId )
|
|
{
|
|
static cppu::OImplementationId id(sal_False);
|
|
pId = &id;
|
|
}
|
|
}
|
|
return pId->getImplementationId();
|
|
}
|
|
|
|
void PreparedStatement::close( ) throw (SQLException, RuntimeException)
|
|
{
|
|
// let the connection die without acquired mutex !
|
|
Reference< XConnection > r;
|
|
Reference< XCloseable > resultSet;
|
|
{
|
|
MutexGuard guard( m_refMutex->mutex );
|
|
m_pSettings = 0;
|
|
r = m_connection;
|
|
m_connection.clear();
|
|
|
|
resultSet = m_lastResultset;
|
|
m_lastResultset.clear();
|
|
}
|
|
if( resultSet.is() )
|
|
{
|
|
resultSet->close();
|
|
}
|
|
}
|
|
|
|
void PreparedStatement::raiseSQLException(
|
|
const char * errorMsg, const char *errorType )
|
|
throw( SQLException )
|
|
{
|
|
OUStringBuffer buf(128);
|
|
buf.appendAscii( "pq_driver: ");
|
|
if( errorType )
|
|
{
|
|
buf.appendAscii( "[" );
|
|
buf.appendAscii( errorType );
|
|
buf.appendAscii( "]" );
|
|
}
|
|
buf.append(
|
|
rtl::OUString( errorMsg, strlen(errorMsg) , m_pSettings->encoding ) );
|
|
buf.appendAscii( " (caused by statement '" );
|
|
buf.appendAscii( m_executedStatement.getStr() );
|
|
buf.appendAscii( "')" );
|
|
OUString error = buf.makeStringAndClear();
|
|
log( m_pSettings, LogLevel::ERROR, error );
|
|
throw SQLException( buf.makeStringAndClear(), *this, OUString(), 1, Any() );
|
|
}
|
|
|
|
Reference< XResultSet > PreparedStatement::executeQuery( )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
Reference< XCloseable > lastResultSet = m_lastResultset;
|
|
if( lastResultSet.is() )
|
|
lastResultSet->close();
|
|
|
|
if( ! execute( ) )
|
|
{
|
|
raiseSQLException( "not a query" );
|
|
}
|
|
return Reference< XResultSet > ( m_lastResultset, com::sun::star::uno::UNO_QUERY );
|
|
}
|
|
|
|
sal_Int32 PreparedStatement::executeUpdate( )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
if( execute( ) )
|
|
{
|
|
raiseSQLException( "not a command" );
|
|
}
|
|
return m_multipleResultUpdateCount;
|
|
}
|
|
|
|
sal_Bool PreparedStatement::execute( )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
osl::MutexGuard guard( m_refMutex->mutex );
|
|
|
|
OStringBuffer buf( m_stmt.getLength() *2 );
|
|
|
|
OStringVector::size_type vars = 0;
|
|
for( OStringVector::size_type i = 0 ; i < m_splittedStatement.size() ; ++i )
|
|
{
|
|
// LEM TODO: instead of this manual mucking with SQL
|
|
// could we use PQexecParams / PQExecPrepared / ...?
|
|
// Only snafu is giving the types of the parameters and
|
|
// that it needs $1, $2, etc instead of "?"
|
|
const OString &str = m_splittedStatement[i];
|
|
// printf( "Splitted %d %s\n" , i , str.getStr() );
|
|
if( isQuoted( str ) )
|
|
{
|
|
buf.append( str );
|
|
}
|
|
else
|
|
{
|
|
int start = 0,index;
|
|
for( index = 1 ; index < str.getLength() ; index ++ )
|
|
{
|
|
if( str[index] == '?' )
|
|
{
|
|
buf.append( str.getStr()+start, index - start );
|
|
buf.append( m_vars[vars] );
|
|
vars ++;
|
|
start =index+1;
|
|
}
|
|
else
|
|
{
|
|
if ( isNamedParameterStart( str, index ) )
|
|
{
|
|
buf.append( str.getStr()+start, index -start );
|
|
buf.append( m_vars[vars] );
|
|
|
|
// skip to the end of the named parameter
|
|
for( ; index < str.getLength() &&
|
|
! ( isWhitespace( str[index] ) || isOperator( str[index] ) ) ; index ++ );
|
|
start = index;
|
|
vars ++;
|
|
}
|
|
}
|
|
}
|
|
// if( index +1 >= str.getLength() )
|
|
// {
|
|
buf.append( str.getStr() + start, index -start );
|
|
// }
|
|
}
|
|
}
|
|
|
|
m_executedStatement = buf.makeStringAndClear();
|
|
|
|
m_lastResultset.clear();
|
|
m_lastTableInserted = rtl::OUString();
|
|
|
|
struct CommandData data;
|
|
data.refMutex = m_refMutex;
|
|
data.ppSettings = &m_pSettings;
|
|
data.pLastOidInserted = &m_lastOidInserted;
|
|
data.pLastQuery = &m_lastQuery;
|
|
data.pMultipleResultUpdateCount = &m_multipleResultUpdateCount;
|
|
data.pMultipleResultAvailable = &m_multipleResultAvailable;
|
|
data.pLastTableInserted = &m_lastTableInserted;
|
|
data.pLastResultset = &m_lastResultset;
|
|
data.owner = *this;
|
|
data.tableSupplier = Reference< com::sun::star::sdbcx::XTablesSupplier >( m_connection, UNO_QUERY );
|
|
data.concurrency = extractIntProperty( this, getStatics().RESULT_SET_CONCURRENCY );
|
|
|
|
return executePostgresCommand( m_executedStatement , &data ); // see pq_statement.cxx
|
|
}
|
|
|
|
Reference< XConnection > PreparedStatement::getConnection( )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
Reference< XConnection > ret;
|
|
{
|
|
MutexGuard guard( m_refMutex->mutex );
|
|
checkClosed();
|
|
ret = m_connection;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
void PreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
(void)sqlType;
|
|
MutexGuard guard( m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
m_vars[parameterIndex-1] = OString( "NULL" );
|
|
}
|
|
|
|
void PreparedStatement::setObjectNull(
|
|
sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
(void) sqlType; (void) typeName;
|
|
MutexGuard guard( m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
m_vars[parameterIndex-1] = OString( "NULL" );
|
|
}
|
|
|
|
|
|
void PreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
MutexGuard guard(m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
if( x )
|
|
m_vars[parameterIndex-1] = OString( "'t'" );
|
|
else
|
|
m_vars[parameterIndex-1] = OString( "'f'" );
|
|
}
|
|
|
|
void PreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
setInt(parameterIndex,x);
|
|
}
|
|
|
|
void PreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
setInt(parameterIndex, x );
|
|
}
|
|
|
|
void PreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
// printf( "setString %d %d\n ", parameterIndex, x);
|
|
MutexGuard guard(m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
OStringBuffer buf( 20 );
|
|
buf.append( "'" );
|
|
buf.append( (sal_Int32) x );
|
|
buf.append( "'" );
|
|
m_vars[parameterIndex-1] = buf.makeStringAndClear();
|
|
}
|
|
|
|
void PreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
MutexGuard guard(m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
OStringBuffer buf( 20 );
|
|
buf.append( "'" );
|
|
buf.append( (sal_Int64) x );
|
|
buf.append( "'" );
|
|
m_vars[parameterIndex-1] = buf.makeStringAndClear();
|
|
}
|
|
|
|
void PreparedStatement::setFloat( sal_Int32 parameterIndex, float x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
MutexGuard guard(m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
OStringBuffer buf( 20 );
|
|
buf.append( "'" );
|
|
buf.append( x );
|
|
buf.append( "'" );
|
|
m_vars[parameterIndex-1] = buf.makeStringAndClear();
|
|
}
|
|
|
|
void PreparedStatement::setDouble( sal_Int32 parameterIndex, double x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
MutexGuard guard(m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
OStringBuffer buf( 20 );
|
|
buf.append( "'" );
|
|
buf.append( x );
|
|
buf.append( "'" );
|
|
m_vars[parameterIndex-1] = buf.makeStringAndClear();
|
|
}
|
|
|
|
void PreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
// printf( "setString %d %s\n ", parameterIndex,
|
|
// OUStringToOString( x , RTL_TEXTENCODING_ASCII_US ).getStr());
|
|
MutexGuard guard(m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
OStringBuffer buf( 20 );
|
|
buf.append( "'" );
|
|
OString y = OUStringToOString( x, m_pSettings->encoding );
|
|
buf.ensureCapacity( y.getLength() * 2 + 2 );
|
|
int len = PQescapeString( ((char*)buf.getStr())+1, y.getStr() , y.getLength() );
|
|
buf.setLength( 1 + len );
|
|
buf.append( "'" );
|
|
m_vars[parameterIndex-1] = buf.makeStringAndClear();
|
|
}
|
|
|
|
void PreparedStatement::setBytes(
|
|
sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
MutexGuard guard(m_refMutex->mutex );
|
|
checkClosed();
|
|
checkColumnIndex( parameterIndex );
|
|
OStringBuffer buf( 20 );
|
|
buf.append( "'" );
|
|
size_t len;
|
|
unsigned char * escapedString =
|
|
PQescapeBytea( (unsigned char *)x.getConstArray(), x.getLength(), &len);
|
|
if( ! escapedString )
|
|
{
|
|
throw SQLException(
|
|
ASCII_STR("pq_preparedstatement.setBytes: Error during converting bytesequence to an SQL conform string" ),
|
|
*this, OUString(), 1, Any() );
|
|
}
|
|
buf.append( (const sal_Char *)escapedString, len -1 );
|
|
free( escapedString );
|
|
buf.append( "'" );
|
|
m_vars[parameterIndex-1] = buf.makeStringAndClear();
|
|
}
|
|
|
|
|
|
void PreparedStatement::setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
setString( parameterIndex, date2String( x ) );
|
|
}
|
|
|
|
void PreparedStatement::setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
setString( parameterIndex, time2String( x ) );
|
|
}
|
|
|
|
void PreparedStatement::setTimestamp(
|
|
sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
setString( parameterIndex, dateTime2String( x ) );
|
|
}
|
|
|
|
void PreparedStatement::setBinaryStream(
|
|
sal_Int32 parameterIndex,
|
|
const Reference< ::com::sun::star::io::XInputStream >& x,
|
|
sal_Int32 length )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
(void) parameterIndex; (void)x; (void) length;
|
|
throw SQLException(
|
|
ASCII_STR( "pq_preparedstatement: setBinaryStream not implemented" ),
|
|
*this, OUString(), 1, Any () );
|
|
}
|
|
|
|
void PreparedStatement::setCharacterStream(
|
|
sal_Int32 parameterIndex,
|
|
const Reference< ::com::sun::star::io::XInputStream >& x,
|
|
sal_Int32 length )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
(void) parameterIndex; (void)x; (void) length;
|
|
throw SQLException(
|
|
ASCII_STR( "pq_preparedstatement: setCharacterStream not implemented" ),
|
|
*this, OUString(), 1, Any () );
|
|
}
|
|
|
|
void PreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
if( ! implSetObject( this, parameterIndex, x ))
|
|
{
|
|
OUStringBuffer buf;
|
|
buf.append( ASCII_STR("pq_preparedstatement::setObject: can't convert value of type " ) );
|
|
buf.append( x.getValueTypeName() );
|
|
throw SQLException( buf.makeStringAndClear(), *this, OUString(), 1, Any () );
|
|
}
|
|
}
|
|
|
|
void PreparedStatement::setObjectWithInfo(
|
|
sal_Int32 parameterIndex,
|
|
const Any& x,
|
|
sal_Int32 targetSqlType,
|
|
sal_Int32 scale )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
(void) scale;
|
|
if( com::sun::star::sdbc::DataType::DECIMAL == targetSqlType ||
|
|
com::sun::star::sdbc::DataType::NUMERIC == targetSqlType )
|
|
{
|
|
double myDouble;
|
|
OUString myString;
|
|
if( x >>= myDouble )
|
|
{
|
|
myString = OUString::valueOf( myDouble );
|
|
}
|
|
else
|
|
{
|
|
x >>= myString;
|
|
}
|
|
if( myString.getLength() )
|
|
{
|
|
// printf( "setObjectWithInfo %s\n", OUStringToOString(myString,RTL_TEXTENCODING_ASCII_US).getStr());
|
|
setString( parameterIndex, myString );
|
|
}
|
|
else
|
|
{
|
|
OUStringBuffer buf;
|
|
buf.append( ASCII_STR("pq_preparedstatement::setObjectWithInfo: can't convert value of type " ) );
|
|
buf.append( x.getValueTypeName() );
|
|
buf.append( ASCII_STR(" to type DECIMAL or NUMERIC" ) );
|
|
throw SQLException( buf.makeStringAndClear(), *this, OUString(), 1, Any () );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
setObject( parameterIndex, x );
|
|
}
|
|
|
|
}
|
|
|
|
void PreparedStatement::setRef(
|
|
sal_Int32 parameterIndex,
|
|
const Reference< XRef >& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
(void) parameterIndex; (void)x;
|
|
throw SQLException(
|
|
ASCII_STR( "pq_preparedstatement: setRef not implemented" ),
|
|
*this, OUString(), 1, Any () );
|
|
}
|
|
|
|
void PreparedStatement::setBlob(
|
|
sal_Int32 parameterIndex,
|
|
const Reference< XBlob >& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
(void) parameterIndex; (void)x;
|
|
throw SQLException(
|
|
ASCII_STR( "pq_preparedstatement: setBlob not implemented" ),
|
|
*this, OUString(), 1, Any () );
|
|
}
|
|
|
|
void PreparedStatement::setClob(
|
|
sal_Int32 parameterIndex,
|
|
const Reference< XClob >& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
(void) parameterIndex; (void)x;
|
|
throw SQLException(
|
|
ASCII_STR( "pq_preparedstatement: setClob not implemented" ),
|
|
*this, OUString(), 1, Any () );
|
|
}
|
|
|
|
void PreparedStatement::setArray(
|
|
sal_Int32 parameterIndex,
|
|
const Reference< XArray >& x )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
setString( parameterIndex, array2String( x->getArray( 0 ) ) );
|
|
}
|
|
|
|
void PreparedStatement::clearParameters( )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
MutexGuard guard(m_refMutex->mutex );
|
|
m_vars = OStringVector ( m_vars.size() );
|
|
}
|
|
|
|
Any PreparedStatement::getWarnings( )
|
|
throw (SQLException,RuntimeException)
|
|
{
|
|
return Any();
|
|
}
|
|
|
|
void PreparedStatement::clearWarnings( )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
}
|
|
|
|
Reference< ::com::sun::star::sdbc::XResultSetMetaData > PreparedStatement::getMetaData()
|
|
throw (SQLException,RuntimeException)
|
|
{
|
|
Reference< com::sun::star::sdbc::XResultSetMetaData > ret;
|
|
Reference< com::sun::star::sdbc::XResultSetMetaDataSupplier > supplier( m_lastResultset, UNO_QUERY );
|
|
if( supplier.is() )
|
|
ret = supplier->getMetaData();
|
|
return ret;
|
|
}
|
|
|
|
::cppu::IPropertyArrayHelper & PreparedStatement::getInfoHelper()
|
|
{
|
|
return getPreparedStatementPropertyArrayHelper();
|
|
}
|
|
|
|
|
|
sal_Bool PreparedStatement::convertFastPropertyValue(
|
|
Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
|
|
throw (IllegalArgumentException)
|
|
{
|
|
sal_Bool bRet;
|
|
rOldValue = m_props[nHandle];
|
|
switch( nHandle )
|
|
{
|
|
case PREPARED_STATEMENT_CURSOR_NAME:
|
|
{
|
|
OUString val;
|
|
bRet = ( rValue >>= val );
|
|
rConvertedValue = makeAny( val );
|
|
break;
|
|
}
|
|
case PREPARED_STATEMENT_ESCAPE_PROCESSING:
|
|
{
|
|
sal_Bool val;
|
|
bRet = ( rValue >>= val );
|
|
rConvertedValue = makeAny( val );
|
|
break;
|
|
}
|
|
case PREPARED_STATEMENT_FETCH_DIRECTION:
|
|
case PREPARED_STATEMENT_FETCH_SIZE:
|
|
case PREPARED_STATEMENT_MAX_FIELD_SIZE:
|
|
case PREPARED_STATEMENT_MAX_ROWS:
|
|
case PREPARED_STATEMENT_QUERY_TIME_OUT:
|
|
case PREPARED_STATEMENT_RESULT_SET_CONCURRENCY:
|
|
case PREPARED_STATEMENT_RESULT_SET_TYPE:
|
|
{
|
|
sal_Int32 val;
|
|
bRet = ( rValue >>= val );
|
|
rConvertedValue = makeAny( val );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
OUStringBuffer buf(128);
|
|
buf.appendAscii( "pq_statement: Invalid property handle (" );
|
|
buf.append( nHandle );
|
|
buf.appendAscii( ")" );
|
|
throw IllegalArgumentException( buf.makeStringAndClear(), *this, 2 );
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
|
|
void PreparedStatement::setFastPropertyValue_NoBroadcast(
|
|
sal_Int32 nHandle,const Any& rValue ) throw (Exception)
|
|
{
|
|
m_props[nHandle] = rValue;
|
|
}
|
|
|
|
void PreparedStatement::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
|
|
{
|
|
rValue = m_props[nHandle];
|
|
}
|
|
|
|
Reference < XPropertySetInfo > PreparedStatement::getPropertySetInfo()
|
|
throw(RuntimeException)
|
|
{
|
|
return OPropertySetHelper::createPropertySetInfo( getPreparedStatementPropertyArrayHelper() );
|
|
}
|
|
|
|
void PreparedStatement::disposing()
|
|
{
|
|
close();
|
|
}
|
|
|
|
|
|
Reference< XResultSet > PreparedStatement::getResultSet( )
|
|
throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
|
|
{
|
|
return Reference< XResultSet > ( m_lastResultset, com::sun::star::uno::UNO_QUERY );
|
|
}
|
|
sal_Int32 PreparedStatement::getUpdateCount( )
|
|
throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
|
|
{
|
|
return m_multipleResultUpdateCount;
|
|
}
|
|
sal_Bool PreparedStatement::getMoreResults( )
|
|
throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
|
|
{
|
|
return sal_False;
|
|
}
|
|
|
|
Reference< XResultSet > PreparedStatement::getGeneratedValues( )
|
|
throw (SQLException, RuntimeException)
|
|
{
|
|
osl::MutexGuard guard( m_refMutex->mutex );
|
|
return getGeneratedValuesFromLastInsert(
|
|
m_pSettings, m_connection, m_lastOidInserted, m_lastTableInserted, m_lastQuery );
|
|
}
|
|
|
|
|
|
}
|