Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * Effective License of whole file:
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License version 2.1, as published by the Free Software Foundation.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 : : * MA 02111-1307 USA
19 : : *
20 : : * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
21 : : *
22 : : * The Contents of this file are made available subject to the terms of
23 : : * the GNU Lesser General Public License Version 2.1
24 : : *
25 : : * Copyright: 2000 by Sun Microsystems, Inc.
26 : : *
27 : : * Contributor(s): Joerg Budischewski
28 : : *
29 : : * All parts contributed on or after August 2011:
30 : : *
31 : : * Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
32 : : *
33 : : * The contents of this file are subject to the Mozilla Public License Version
34 : : * 1.1 (the "License"); you may not use this file except in compliance with
35 : : * the License or as specified alternatively below. You may obtain a copy of
36 : : * the License at http://www.mozilla.org/MPL/
37 : : *
38 : : * Software distributed under the License is distributed on an "AS IS" basis,
39 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
40 : : * for the specific language governing rights and limitations under the
41 : : * License.
42 : : *
43 : : * Major Contributor(s):
44 : : * [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
45 : : *
46 : : * All Rights Reserved.
47 : : *
48 : : * For minor contributions see the git repository.
49 : : *
50 : : * Alternatively, the contents of this file may be used under the terms of
51 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
52 : : * the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
53 : : * in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
54 : : * instead of those above.
55 : : *
56 : : ************************************************************************/
57 : :
58 : : #include "pq_preparedstatement.hxx"
59 : : #include "pq_resultset.hxx"
60 : : #include "pq_tools.hxx"
61 : : #include "pq_statics.hxx"
62 : : #include "pq_statement.hxx"
63 : :
64 : : #include <rtl/strbuf.hxx>
65 : : #include <rtl/ustrbuf.hxx>
66 : :
67 : :
68 : : #include <cppuhelper/typeprovider.hxx>
69 : : #include <cppuhelper/queryinterface.hxx>
70 : :
71 : : #include <com/sun/star/beans/PropertyAttribute.hpp>
72 : :
73 : : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
74 : : #include <com/sun/star/sdbc/ResultSetType.hpp>
75 : :
76 : : #include <string.h>
77 : :
78 : : using osl::Mutex;
79 : : using osl::MutexGuard;
80 : :
81 : : using rtl::OUString;
82 : : using rtl::OUStringToOString;
83 : : using rtl::OStringToOUString;
84 : : using rtl::OUStringBuffer;
85 : : using rtl::OStringBuffer;
86 : : using rtl::OString;
87 : :
88 : : using com::sun::star::uno::Any;
89 : : using com::sun::star::uno::makeAny;
90 : : using com::sun::star::uno::Type;
91 : : using com::sun::star::uno::RuntimeException;
92 : : using com::sun::star::uno::Exception;
93 : : using com::sun::star::uno::Sequence;
94 : : using com::sun::star::uno::Reference;
95 : : using com::sun::star::uno::XInterface;
96 : : using com::sun::star::uno::UNO_QUERY;
97 : :
98 : : using com::sun::star::lang::IllegalArgumentException;
99 : :
100 : : using com::sun::star::sdbc::XWarningsSupplier;
101 : : using com::sun::star::sdbc::XCloseable;
102 : : using com::sun::star::sdbc::XPreparedStatement;
103 : : using com::sun::star::sdbc::XParameters;
104 : : using com::sun::star::sdbc::XResultSet;
105 : : using com::sun::star::sdbc::XRef;
106 : : using com::sun::star::sdbc::XBlob;
107 : : using com::sun::star::sdbc::XClob;
108 : : using com::sun::star::sdbc::XArray;
109 : : using com::sun::star::sdbc::XConnection;
110 : : using com::sun::star::sdbc::XGeneratedResultSet;
111 : : using com::sun::star::sdbc::SQLException;
112 : :
113 : : using com::sun::star::beans::Property;
114 : : using com::sun::star::beans::XPropertySetInfo;
115 : : using com::sun::star::beans::XPropertySet;
116 : : using com::sun::star::beans::XMultiPropertySet;
117 : : using com::sun::star::beans::XFastPropertySet;
118 : :
119 : : #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
120 : : namespace pq_sdbc_driver
121 : : {
122 : 0 : static ::cppu::IPropertyArrayHelper & getPreparedStatementPropertyArrayHelper()
123 : : {
124 : : static ::cppu::IPropertyArrayHelper *pArrayHelper;
125 : 0 : if( ! pArrayHelper )
126 : : {
127 : 0 : MutexGuard guard( Mutex::getGlobalMutex() );
128 : 0 : if( ! pArrayHelper )
129 : : {
130 : : static Property aTable[] =
131 : : {
132 : : Property(
133 : : OUString( RTL_CONSTASCII_USTRINGPARAM("CursorName") ), 0,
134 : 0 : ::getCppuType( (OUString *)0) , 0 ),
135 : : Property(
136 : : OUString( RTL_CONSTASCII_USTRINGPARAM("EscapeProcessing") ), 1,
137 : 0 : ::getBooleanCppuType() , 0 ),
138 : : Property(
139 : : OUString( RTL_CONSTASCII_USTRINGPARAM("FetchDirection") ), 2,
140 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
141 : : Property(
142 : : OUString( RTL_CONSTASCII_USTRINGPARAM("FetchSize") ), 3,
143 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
144 : : Property(
145 : : OUString( RTL_CONSTASCII_USTRINGPARAM("MaxFieldSize") ), 4,
146 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
147 : : Property(
148 : : OUString( RTL_CONSTASCII_USTRINGPARAM("MaxRows") ), 5,
149 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
150 : : Property(
151 : : OUString( RTL_CONSTASCII_USTRINGPARAM("QueryTimeOut") ), 6,
152 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
153 : : Property(
154 : : OUString( RTL_CONSTASCII_USTRINGPARAM("ResultSetConcurrency") ), 7,
155 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
156 : : Property(
157 : : OUString( RTL_CONSTASCII_USTRINGPARAM("ResultSetType") ), 8,
158 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 )
159 : 0 : };
160 : : OSL_ASSERT( sizeof(aTable)/ sizeof(Property) == PREPARED_STATEMENT_SIZE );
161 : 0 : static ::cppu::OPropertyArrayHelper arrayHelper( aTable, PREPARED_STATEMENT_SIZE, sal_True );
162 : 0 : pArrayHelper = &arrayHelper;
163 : 0 : }
164 : : }
165 : 0 : return *pArrayHelper;
166 : : }
167 : :
168 : 0 : static bool isOperator( char c )
169 : : {
170 : : static const char * operators = "<>=()!/&%.,;";
171 : :
172 : 0 : const char * w = operators;
173 : 0 : for( ; *w && *w != c ; w ++);
174 : 0 : return *w != 0;
175 : : }
176 : :
177 : 0 : static bool isNamedParameterStart( const rtl::OString & o , int index )
178 : : {
179 : 0 : return o[index] == ':' && (
180 : 0 : isWhitespace( o[index-1] ) || isOperator(o[index-1]) );
181 : : }
182 : :
183 : 0 : static bool isQuoted( const rtl::OString & str )
184 : : {
185 : 0 : return str[0] == '"' || str[0] == '\'';
186 : : }
187 : :
188 : 0 : PreparedStatement::PreparedStatement(
189 : : const ::rtl::Reference< RefCountedMutex > & refMutex,
190 : : const Reference< XConnection > & conn,
191 : : struct ConnectionSettings *pSettings,
192 : : const ::rtl::OString & stmt )
193 : 0 : : OComponentHelper( refMutex->mutex ),
194 : : OPropertySetHelper( OComponentHelper::rBHelper ),
195 : : m_connection( conn ),
196 : : m_pSettings( pSettings ),
197 : : m_stmt( stmt ),
198 : : m_refMutex( refMutex ),
199 : 0 : m_lastOidInserted( InvalidOid )
200 : : {
201 : 0 : m_props[PREPARED_STATEMENT_QUERY_TIME_OUT] = makeAny( (sal_Int32)0 );
202 : 0 : m_props[PREPARED_STATEMENT_MAX_ROWS] = makeAny( (sal_Int32)0 );
203 : : m_props[PREPARED_STATEMENT_RESULT_SET_CONCURRENCY] = makeAny(
204 : 0 : com::sun::star::sdbc::ResultSetConcurrency::READ_ONLY );
205 : : m_props[PREPARED_STATEMENT_RESULT_SET_TYPE] = makeAny(
206 : 0 : com::sun::star::sdbc::ResultSetType::SCROLL_INSENSITIVE );
207 : :
208 : 0 : splitSQL( m_stmt, m_splittedStatement );
209 : 0 : int elements = 0;
210 : 0 : for( int i = 0, max = m_splittedStatement.size(); i < max ; i ++ )
211 : : {
212 : 0 : const OString &str = m_splittedStatement[i];
213 : : // ignore quoted strings ....
214 : 0 : if( ! isQuoted( str ) )
215 : : {
216 : : // the ':' cannot be the first or the last part of the
217 : : // token,
218 : : // the ? cannot be the first part of the token , so we start
219 : : // at one
220 : 0 : for( int index = 1 ; index < str.getLength() ; index ++ )
221 : : {
222 : 0 : if( str[index] == '?' ||
223 : 0 : isNamedParameterStart( str , index )
224 : : )
225 : : {
226 : 0 : elements ++;
227 : : }
228 : : }
229 : : }
230 : : }
231 : 0 : m_vars = OStringVector ( elements );
232 : 0 : }
233 : :
234 : 0 : PreparedStatement::~PreparedStatement()
235 : : {
236 : : POSTGRE_TRACE( "dtor PreparedStatement" );
237 : 0 : }
238 : :
239 : 0 : void PreparedStatement::checkColumnIndex( sal_Int32 parameterIndex )
240 : : {
241 : 0 : if( parameterIndex < 1 || parameterIndex > (sal_Int32) m_vars.size() )
242 : : {
243 : 0 : OUStringBuffer buf( 128 );
244 : 0 : buf.appendAscii( "pq_preparedstatement: parameter index out of range (expected 1 to " );
245 : 0 : buf.append( (sal_Int32 ) m_vars.size() );
246 : 0 : buf.appendAscii( ", got " );
247 : 0 : buf.append( parameterIndex );
248 : 0 : buf.appendAscii( ", statement '" );
249 : 0 : buf.append( OStringToOUString( m_stmt, m_pSettings->encoding ) );
250 : 0 : buf.appendAscii( "')" );
251 : 0 : throw SQLException( buf.makeStringAndClear(), *this, OUString(), 1, Any () );
252 : : }
253 : 0 : }
254 : 0 : void PreparedStatement::checkClosed() throw (SQLException, RuntimeException )
255 : : {
256 : 0 : if( ! m_pSettings || ! m_pSettings->pConnection )
257 : : throw SQLException(
258 : : ASCII_STR("pq_driver: PreparedStatement or connection has already been closed !" ),
259 : 0 : *this, OUString(),1,Any());
260 : 0 : }
261 : :
262 : 0 : Any PreparedStatement::queryInterface( const Type & reqType ) throw (RuntimeException)
263 : : {
264 : 0 : Any ret;
265 : :
266 : 0 : ret = OComponentHelper::queryInterface( reqType );
267 : 0 : if( ! ret.hasValue() )
268 : : ret = ::cppu::queryInterface( reqType,
269 : : static_cast< XWarningsSupplier * > ( this ),
270 : : static_cast< XPreparedStatement * > ( this ),
271 : : static_cast< com::sun::star::sdbc::XResultSetMetaDataSupplier * > ( this ),
272 : : static_cast< XParameters * > ( this ),
273 : : static_cast< XCloseable * > ( this ),
274 : : static_cast< XGeneratedResultSet * > ( this ),
275 : : static_cast< XPropertySet * > ( this ),
276 : : static_cast< XMultiPropertySet * > ( this ),
277 : 0 : static_cast< XFastPropertySet * > ( this ) );
278 : 0 : return ret;
279 : : }
280 : :
281 : :
282 : 0 : Sequence< Type > PreparedStatement::getTypes() throw ( RuntimeException )
283 : : {
284 : : static cppu::OTypeCollection *pCollection;
285 : 0 : if( ! pCollection )
286 : : {
287 : 0 : MutexGuard guard( osl::Mutex::getGlobalMutex() );
288 : 0 : if( !pCollection )
289 : : {
290 : : static cppu::OTypeCollection collection(
291 : 0 : getCppuType( (Reference< XWarningsSupplier> *) 0 ),
292 : 0 : getCppuType( (Reference< XPreparedStatement> *) 0 ),
293 : 0 : getCppuType( (Reference< com::sun::star::sdbc::XResultSetMetaDataSupplier> *) 0 ),
294 : 0 : getCppuType( (Reference< XParameters> *) 0 ),
295 : 0 : getCppuType( (Reference< XCloseable> *) 0 ),
296 : 0 : getCppuType( (Reference< XGeneratedResultSet> *) 0 ),
297 : 0 : getCppuType( (Reference< XPropertySet >*) 0 ),
298 : 0 : getCppuType( (Reference< XFastPropertySet > *) 0 ),
299 : 0 : getCppuType( (Reference< XMultiPropertySet > *) 0 ),
300 : 0 : OComponentHelper::getTypes());
301 : 0 : pCollection = &collection;
302 : 0 : }
303 : : }
304 : 0 : return pCollection->getTypes();
305 : : }
306 : :
307 : 0 : Sequence< sal_Int8> PreparedStatement::getImplementationId() throw ( RuntimeException )
308 : : {
309 : : static cppu::OImplementationId *pId;
310 : 0 : if( ! pId )
311 : : {
312 : 0 : MutexGuard guard( osl::Mutex::getGlobalMutex() );
313 : 0 : if( ! pId )
314 : : {
315 : 0 : static cppu::OImplementationId id(sal_False);
316 : 0 : pId = &id;
317 : 0 : }
318 : : }
319 : 0 : return pId->getImplementationId();
320 : : }
321 : :
322 : 0 : void PreparedStatement::close( ) throw (SQLException, RuntimeException)
323 : : {
324 : : // let the connection die without acquired mutex !
325 : 0 : Reference< XConnection > r;
326 : 0 : Reference< XCloseable > resultSet;
327 : : {
328 : 0 : MutexGuard guard( m_refMutex->mutex );
329 : 0 : m_pSettings = 0;
330 : 0 : r = m_connection;
331 : 0 : m_connection.clear();
332 : :
333 : 0 : resultSet = m_lastResultset;
334 : 0 : m_lastResultset.clear();
335 : : }
336 : 0 : if( resultSet.is() )
337 : : {
338 : 0 : resultSet->close();
339 : 0 : }
340 : 0 : }
341 : :
342 : 0 : void PreparedStatement::raiseSQLException(
343 : : const char * errorMsg, const char *errorType )
344 : : throw( SQLException )
345 : : {
346 : 0 : OUStringBuffer buf(128);
347 : 0 : buf.appendAscii( "pq_driver: ");
348 : 0 : if( errorType )
349 : : {
350 : 0 : buf.appendAscii( "[" );
351 : 0 : buf.appendAscii( errorType );
352 : 0 : buf.appendAscii( "]" );
353 : : }
354 : : buf.append(
355 : 0 : rtl::OUString( errorMsg, strlen(errorMsg) , m_pSettings->encoding ) );
356 : 0 : buf.appendAscii( " (caused by statement '" );
357 : 0 : buf.appendAscii( m_executedStatement.getStr() );
358 : 0 : buf.appendAscii( "')" );
359 : 0 : OUString error = buf.makeStringAndClear();
360 : 0 : log( m_pSettings, LogLevel::ERROR, error );
361 : 0 : throw SQLException( buf.makeStringAndClear(), *this, OUString(), 1, Any() );
362 : : }
363 : :
364 : 0 : Reference< XResultSet > PreparedStatement::executeQuery( )
365 : : throw (SQLException, RuntimeException)
366 : : {
367 : 0 : Reference< XCloseable > lastResultSet = m_lastResultset;
368 : 0 : if( lastResultSet.is() )
369 : 0 : lastResultSet->close();
370 : :
371 : 0 : if( ! execute( ) )
372 : : {
373 : 0 : raiseSQLException( "not a query" );
374 : : }
375 : 0 : return Reference< XResultSet > ( m_lastResultset, com::sun::star::uno::UNO_QUERY );
376 : : }
377 : :
378 : 0 : sal_Int32 PreparedStatement::executeUpdate( )
379 : : throw (SQLException, RuntimeException)
380 : : {
381 : 0 : if( execute( ) )
382 : : {
383 : 0 : raiseSQLException( "not a command" );
384 : : }
385 : 0 : return m_multipleResultUpdateCount;
386 : : }
387 : :
388 : 0 : sal_Bool PreparedStatement::execute( )
389 : : throw (SQLException, RuntimeException)
390 : : {
391 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
392 : :
393 : 0 : OStringBuffer buf( m_stmt.getLength() *2 );
394 : :
395 : 0 : OStringVector::size_type vars = 0;
396 : 0 : for( OStringVector::size_type i = 0 ; i < m_splittedStatement.size() ; ++i )
397 : : {
398 : : // LEM TODO: instead of this manual mucking with SQL
399 : : // could we use PQexecParams / PQExecPrepared / ...?
400 : : // Only snafu is giving the types of the parameters and
401 : : // that it needs $1, $2, etc instead of "?"
402 : 0 : const OString &str = m_splittedStatement[i];
403 : : // printf( "Splitted %d %s\n" , i , str.getStr() );
404 : 0 : if( isQuoted( str ) )
405 : : {
406 : 0 : buf.append( str );
407 : : }
408 : : else
409 : : {
410 : 0 : int start = 0,index;
411 : 0 : for( index = 1 ; index < str.getLength() ; index ++ )
412 : : {
413 : 0 : if( str[index] == '?' )
414 : : {
415 : 0 : buf.append( str.getStr()+start, index - start );
416 : 0 : buf.append( m_vars[vars] );
417 : 0 : vars ++;
418 : 0 : start =index+1;
419 : : }
420 : : else
421 : : {
422 : 0 : if ( isNamedParameterStart( str, index ) )
423 : : {
424 : 0 : buf.append( str.getStr()+start, index -start );
425 : 0 : buf.append( m_vars[vars] );
426 : :
427 : : // skip to the end of the named parameter
428 : 0 : for( ; index < str.getLength() &&
429 : 0 : ! ( isWhitespace( str[index] ) || isOperator( str[index] ) ) ; index ++ );
430 : 0 : start = index;
431 : 0 : vars ++;
432 : : }
433 : : }
434 : : }
435 : : // if( index +1 >= str.getLength() )
436 : : // {
437 : 0 : buf.append( str.getStr() + start, index -start );
438 : : // }
439 : : }
440 : : }
441 : :
442 : 0 : m_executedStatement = buf.makeStringAndClear();
443 : :
444 : 0 : m_lastResultset.clear();
445 : 0 : m_lastTableInserted = rtl::OUString();
446 : :
447 : 0 : struct CommandData data;
448 : 0 : data.refMutex = m_refMutex;
449 : 0 : data.ppSettings = &m_pSettings;
450 : 0 : data.pLastOidInserted = &m_lastOidInserted;
451 : 0 : data.pLastQuery = &m_lastQuery;
452 : 0 : data.pMultipleResultUpdateCount = &m_multipleResultUpdateCount;
453 : 0 : data.pMultipleResultAvailable = &m_multipleResultAvailable;
454 : 0 : data.pLastTableInserted = &m_lastTableInserted;
455 : 0 : data.pLastResultset = &m_lastResultset;
456 : 0 : data.owner = *this;
457 : 0 : data.tableSupplier = Reference< com::sun::star::sdbcx::XTablesSupplier >( m_connection, UNO_QUERY );
458 : 0 : data.concurrency = extractIntProperty( this, getStatics().RESULT_SET_CONCURRENCY );
459 : :
460 : 0 : return executePostgresCommand( m_executedStatement , &data ); // see pq_statement.cxx
461 : : }
462 : :
463 : 0 : Reference< XConnection > PreparedStatement::getConnection( )
464 : : throw (SQLException, RuntimeException)
465 : : {
466 : 0 : Reference< XConnection > ret;
467 : : {
468 : 0 : MutexGuard guard( m_refMutex->mutex );
469 : 0 : checkClosed();
470 : 0 : ret = m_connection;
471 : : }
472 : 0 : return ret;
473 : : }
474 : :
475 : :
476 : 0 : void PreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType )
477 : : throw (SQLException, RuntimeException)
478 : : {
479 : : (void)sqlType;
480 : 0 : MutexGuard guard( m_refMutex->mutex );
481 : 0 : checkClosed();
482 : 0 : checkColumnIndex( parameterIndex );
483 : 0 : m_vars[parameterIndex-1] = OString( "NULL" );
484 : 0 : }
485 : :
486 : 0 : void PreparedStatement::setObjectNull(
487 : : sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName )
488 : : throw (SQLException, RuntimeException)
489 : : {
490 : : (void) sqlType; (void) typeName;
491 : 0 : MutexGuard guard( m_refMutex->mutex );
492 : 0 : checkClosed();
493 : 0 : checkColumnIndex( parameterIndex );
494 : 0 : m_vars[parameterIndex-1] = OString( "NULL" );
495 : 0 : }
496 : :
497 : :
498 : 0 : void PreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
499 : : throw (SQLException, RuntimeException)
500 : : {
501 : 0 : MutexGuard guard(m_refMutex->mutex );
502 : 0 : checkClosed();
503 : 0 : checkColumnIndex( parameterIndex );
504 : 0 : if( x )
505 : 0 : m_vars[parameterIndex-1] = OString( "'t'" );
506 : : else
507 : 0 : m_vars[parameterIndex-1] = OString( "'f'" );
508 : 0 : }
509 : :
510 : 0 : void PreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x )
511 : : throw (SQLException, RuntimeException)
512 : : {
513 : 0 : setInt(parameterIndex,x);
514 : 0 : }
515 : :
516 : 0 : void PreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x )
517 : : throw (SQLException, RuntimeException)
518 : : {
519 : 0 : setInt(parameterIndex, x );
520 : 0 : }
521 : :
522 : 0 : void PreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x )
523 : : throw (SQLException, RuntimeException)
524 : : {
525 : : // printf( "setString %d %d\n ", parameterIndex, x);
526 : 0 : MutexGuard guard(m_refMutex->mutex );
527 : 0 : checkClosed();
528 : 0 : checkColumnIndex( parameterIndex );
529 : 0 : OStringBuffer buf( 20 );
530 : 0 : buf.append( "'" );
531 : 0 : buf.append( (sal_Int32) x );
532 : 0 : buf.append( "'" );
533 : 0 : m_vars[parameterIndex-1] = buf.makeStringAndClear();
534 : 0 : }
535 : :
536 : 0 : void PreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x )
537 : : throw (SQLException, RuntimeException)
538 : : {
539 : 0 : MutexGuard guard(m_refMutex->mutex );
540 : 0 : checkClosed();
541 : 0 : checkColumnIndex( parameterIndex );
542 : 0 : OStringBuffer buf( 20 );
543 : 0 : buf.append( "'" );
544 : 0 : buf.append( (sal_Int64) x );
545 : 0 : buf.append( "'" );
546 : 0 : m_vars[parameterIndex-1] = buf.makeStringAndClear();
547 : 0 : }
548 : :
549 : 0 : void PreparedStatement::setFloat( sal_Int32 parameterIndex, float x )
550 : : throw (SQLException, RuntimeException)
551 : : {
552 : 0 : MutexGuard guard(m_refMutex->mutex );
553 : 0 : checkClosed();
554 : 0 : checkColumnIndex( parameterIndex );
555 : 0 : OStringBuffer buf( 20 );
556 : 0 : buf.append( "'" );
557 : 0 : buf.append( x );
558 : 0 : buf.append( "'" );
559 : 0 : m_vars[parameterIndex-1] = buf.makeStringAndClear();
560 : 0 : }
561 : :
562 : 0 : void PreparedStatement::setDouble( sal_Int32 parameterIndex, double x )
563 : : throw (SQLException, RuntimeException)
564 : : {
565 : 0 : MutexGuard guard(m_refMutex->mutex );
566 : 0 : checkClosed();
567 : 0 : checkColumnIndex( parameterIndex );
568 : 0 : OStringBuffer buf( 20 );
569 : 0 : buf.append( "'" );
570 : 0 : buf.append( x );
571 : 0 : buf.append( "'" );
572 : 0 : m_vars[parameterIndex-1] = buf.makeStringAndClear();
573 : 0 : }
574 : :
575 : 0 : void PreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x )
576 : : throw (SQLException, RuntimeException)
577 : : {
578 : : // printf( "setString %d %s\n ", parameterIndex,
579 : : // OUStringToOString( x , RTL_TEXTENCODING_ASCII_US ).getStr());
580 : 0 : MutexGuard guard(m_refMutex->mutex );
581 : 0 : checkClosed();
582 : 0 : checkColumnIndex( parameterIndex );
583 : 0 : OStringBuffer buf( 20 );
584 : 0 : buf.append( "'" );
585 : 0 : OString y = OUStringToOString( x, m_pSettings->encoding );
586 : 0 : buf.ensureCapacity( y.getLength() * 2 + 2 );
587 : 0 : int len = PQescapeString( ((char*)buf.getStr())+1, y.getStr() , y.getLength() );
588 : 0 : buf.setLength( 1 + len );
589 : 0 : buf.append( "'" );
590 : 0 : m_vars[parameterIndex-1] = buf.makeStringAndClear();
591 : 0 : }
592 : :
593 : 0 : void PreparedStatement::setBytes(
594 : : sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
595 : : throw (SQLException, RuntimeException)
596 : : {
597 : 0 : MutexGuard guard(m_refMutex->mutex );
598 : 0 : checkClosed();
599 : 0 : checkColumnIndex( parameterIndex );
600 : 0 : OStringBuffer buf( 20 );
601 : 0 : buf.append( "'" );
602 : : size_t len;
603 : : unsigned char * escapedString =
604 : 0 : PQescapeBytea( (unsigned char *)x.getConstArray(), x.getLength(), &len);
605 : 0 : if( ! escapedString )
606 : : {
607 : : throw SQLException(
608 : : ASCII_STR("pq_preparedstatement.setBytes: Error during converting bytesequence to an SQL conform string" ),
609 : 0 : *this, OUString(), 1, Any() );
610 : : }
611 : 0 : buf.append( (const sal_Char *)escapedString, len -1 );
612 : 0 : free( escapedString );
613 : 0 : buf.append( "'" );
614 : 0 : m_vars[parameterIndex-1] = buf.makeStringAndClear();
615 : 0 : }
616 : :
617 : :
618 : 0 : void PreparedStatement::setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x )
619 : : throw (SQLException, RuntimeException)
620 : : {
621 : 0 : setString( parameterIndex, date2String( x ) );
622 : 0 : }
623 : :
624 : 0 : void PreparedStatement::setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x )
625 : : throw (SQLException, RuntimeException)
626 : : {
627 : 0 : setString( parameterIndex, time2String( x ) );
628 : 0 : }
629 : :
630 : 0 : void PreparedStatement::setTimestamp(
631 : : sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x )
632 : : throw (SQLException, RuntimeException)
633 : : {
634 : 0 : setString( parameterIndex, dateTime2String( x ) );
635 : 0 : }
636 : :
637 : 0 : void PreparedStatement::setBinaryStream(
638 : : sal_Int32 parameterIndex,
639 : : const Reference< ::com::sun::star::io::XInputStream >& x,
640 : : sal_Int32 length )
641 : : throw (SQLException, RuntimeException)
642 : : {
643 : : (void) parameterIndex; (void)x; (void) length;
644 : : throw SQLException(
645 : : ASCII_STR( "pq_preparedstatement: setBinaryStream not implemented" ),
646 : 0 : *this, OUString(), 1, Any () );
647 : : }
648 : :
649 : 0 : void PreparedStatement::setCharacterStream(
650 : : sal_Int32 parameterIndex,
651 : : const Reference< ::com::sun::star::io::XInputStream >& x,
652 : : sal_Int32 length )
653 : : throw (SQLException, RuntimeException)
654 : : {
655 : : (void) parameterIndex; (void)x; (void) length;
656 : : throw SQLException(
657 : : ASCII_STR( "pq_preparedstatement: setCharacterStream not implemented" ),
658 : 0 : *this, OUString(), 1, Any () );
659 : : }
660 : :
661 : 0 : void PreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
662 : : throw (SQLException, RuntimeException)
663 : : {
664 : 0 : if( ! implSetObject( this, parameterIndex, x ))
665 : : {
666 : 0 : OUStringBuffer buf;
667 : 0 : buf.append( ASCII_STR("pq_preparedstatement::setObject: can't convert value of type " ) );
668 : 0 : buf.append( x.getValueTypeName() );
669 : 0 : throw SQLException( buf.makeStringAndClear(), *this, OUString(), 1, Any () );
670 : : }
671 : 0 : }
672 : :
673 : 0 : void PreparedStatement::setObjectWithInfo(
674 : : sal_Int32 parameterIndex,
675 : : const Any& x,
676 : : sal_Int32 targetSqlType,
677 : : sal_Int32 scale )
678 : : throw (SQLException, RuntimeException)
679 : : {
680 : : (void) scale;
681 : 0 : if( com::sun::star::sdbc::DataType::DECIMAL == targetSqlType ||
682 : : com::sun::star::sdbc::DataType::NUMERIC == targetSqlType )
683 : : {
684 : 0 : double myDouble = 0.0;
685 : 0 : OUString myString;
686 : 0 : if( x >>= myDouble )
687 : : {
688 : 0 : myString = OUString::valueOf( myDouble );
689 : : }
690 : : else
691 : : {
692 : 0 : x >>= myString;
693 : : }
694 : 0 : if( myString.getLength() )
695 : : {
696 : : // printf( "setObjectWithInfo %s\n", OUStringToOString(myString,RTL_TEXTENCODING_ASCII_US).getStr());
697 : 0 : setString( parameterIndex, myString );
698 : : }
699 : : else
700 : : {
701 : 0 : OUStringBuffer buf;
702 : 0 : buf.append( ASCII_STR("pq_preparedstatement::setObjectWithInfo: can't convert value of type " ) );
703 : 0 : buf.append( x.getValueTypeName() );
704 : 0 : buf.append( ASCII_STR(" to type DECIMAL or NUMERIC" ) );
705 : 0 : throw SQLException( buf.makeStringAndClear(), *this, OUString(), 1, Any () );
706 : 0 : }
707 : : }
708 : : else
709 : : {
710 : 0 : setObject( parameterIndex, x );
711 : : }
712 : :
713 : 0 : }
714 : :
715 : 0 : void PreparedStatement::setRef(
716 : : sal_Int32 parameterIndex,
717 : : const Reference< XRef >& x )
718 : : throw (SQLException, RuntimeException)
719 : : {
720 : : (void) parameterIndex; (void)x;
721 : : throw SQLException(
722 : : ASCII_STR( "pq_preparedstatement: setRef not implemented" ),
723 : 0 : *this, OUString(), 1, Any () );
724 : : }
725 : :
726 : 0 : void PreparedStatement::setBlob(
727 : : sal_Int32 parameterIndex,
728 : : const Reference< XBlob >& x )
729 : : throw (SQLException, RuntimeException)
730 : : {
731 : : (void) parameterIndex; (void)x;
732 : : throw SQLException(
733 : : ASCII_STR( "pq_preparedstatement: setBlob not implemented" ),
734 : 0 : *this, OUString(), 1, Any () );
735 : : }
736 : :
737 : 0 : void PreparedStatement::setClob(
738 : : sal_Int32 parameterIndex,
739 : : const Reference< XClob >& x )
740 : : throw (SQLException, RuntimeException)
741 : : {
742 : : (void) parameterIndex; (void)x;
743 : : throw SQLException(
744 : : ASCII_STR( "pq_preparedstatement: setClob not implemented" ),
745 : 0 : *this, OUString(), 1, Any () );
746 : : }
747 : :
748 : 0 : void PreparedStatement::setArray(
749 : : sal_Int32 parameterIndex,
750 : : const Reference< XArray >& x )
751 : : throw (SQLException, RuntimeException)
752 : : {
753 : 0 : setString( parameterIndex, array2String( x->getArray( 0 ) ) );
754 : 0 : }
755 : :
756 : 0 : void PreparedStatement::clearParameters( )
757 : : throw (SQLException, RuntimeException)
758 : : {
759 : 0 : MutexGuard guard(m_refMutex->mutex );
760 : 0 : m_vars = OStringVector ( m_vars.size() );
761 : 0 : }
762 : :
763 : 0 : Any PreparedStatement::getWarnings( )
764 : : throw (SQLException,RuntimeException)
765 : : {
766 : 0 : return Any();
767 : : }
768 : :
769 : 0 : void PreparedStatement::clearWarnings( )
770 : : throw (SQLException, RuntimeException)
771 : : {
772 : 0 : }
773 : :
774 : 0 : Reference< ::com::sun::star::sdbc::XResultSetMetaData > PreparedStatement::getMetaData()
775 : : throw (SQLException,RuntimeException)
776 : : {
777 : 0 : Reference< com::sun::star::sdbc::XResultSetMetaData > ret;
778 : 0 : Reference< com::sun::star::sdbc::XResultSetMetaDataSupplier > supplier( m_lastResultset, UNO_QUERY );
779 : 0 : if( supplier.is() )
780 : 0 : ret = supplier->getMetaData();
781 : 0 : return ret;
782 : : }
783 : :
784 : 0 : ::cppu::IPropertyArrayHelper & PreparedStatement::getInfoHelper()
785 : : {
786 : 0 : return getPreparedStatementPropertyArrayHelper();
787 : : }
788 : :
789 : :
790 : 0 : sal_Bool PreparedStatement::convertFastPropertyValue(
791 : : Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
792 : : throw (IllegalArgumentException)
793 : : {
794 : : sal_Bool bRet;
795 : 0 : rOldValue = m_props[nHandle];
796 : 0 : switch( nHandle )
797 : : {
798 : : case PREPARED_STATEMENT_CURSOR_NAME:
799 : : {
800 : 0 : OUString val;
801 : 0 : bRet = ( rValue >>= val );
802 : 0 : rConvertedValue = makeAny( val );
803 : 0 : break;
804 : : }
805 : : case PREPARED_STATEMENT_ESCAPE_PROCESSING:
806 : : {
807 : : sal_Bool val;
808 : 0 : bRet = ( rValue >>= val );
809 : 0 : rConvertedValue = makeAny( val );
810 : : break;
811 : : }
812 : : case PREPARED_STATEMENT_FETCH_DIRECTION:
813 : : case PREPARED_STATEMENT_FETCH_SIZE:
814 : : case PREPARED_STATEMENT_MAX_FIELD_SIZE:
815 : : case PREPARED_STATEMENT_MAX_ROWS:
816 : : case PREPARED_STATEMENT_QUERY_TIME_OUT:
817 : : case PREPARED_STATEMENT_RESULT_SET_CONCURRENCY:
818 : : case PREPARED_STATEMENT_RESULT_SET_TYPE:
819 : : {
820 : : sal_Int32 val;
821 : 0 : bRet = ( rValue >>= val );
822 : 0 : rConvertedValue = makeAny( val );
823 : : break;
824 : : }
825 : : default:
826 : : {
827 : 0 : OUStringBuffer buf(128);
828 : 0 : buf.appendAscii( "pq_statement: Invalid property handle (" );
829 : 0 : buf.append( nHandle );
830 : 0 : buf.appendAscii( ")" );
831 : 0 : throw IllegalArgumentException( buf.makeStringAndClear(), *this, 2 );
832 : : }
833 : : }
834 : 0 : return bRet;
835 : : }
836 : :
837 : :
838 : 0 : void PreparedStatement::setFastPropertyValue_NoBroadcast(
839 : : sal_Int32 nHandle,const Any& rValue ) throw (Exception)
840 : : {
841 : 0 : m_props[nHandle] = rValue;
842 : 0 : }
843 : :
844 : 0 : void PreparedStatement::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
845 : : {
846 : 0 : rValue = m_props[nHandle];
847 : 0 : }
848 : :
849 : 0 : Reference < XPropertySetInfo > PreparedStatement::getPropertySetInfo()
850 : : throw(RuntimeException)
851 : : {
852 : 0 : return OPropertySetHelper::createPropertySetInfo( getPreparedStatementPropertyArrayHelper() );
853 : : }
854 : :
855 : 0 : void PreparedStatement::disposing()
856 : : {
857 : 0 : close();
858 : 0 : }
859 : :
860 : :
861 : 0 : Reference< XResultSet > PreparedStatement::getResultSet( )
862 : : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
863 : : {
864 : 0 : return Reference< XResultSet > ( m_lastResultset, com::sun::star::uno::UNO_QUERY );
865 : : }
866 : 0 : sal_Int32 PreparedStatement::getUpdateCount( )
867 : : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
868 : : {
869 : 0 : return m_multipleResultUpdateCount;
870 : : }
871 : 0 : sal_Bool PreparedStatement::getMoreResults( )
872 : : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
873 : : {
874 : 0 : return sal_False;
875 : : }
876 : :
877 : 0 : Reference< XResultSet > PreparedStatement::getGeneratedValues( )
878 : : throw (SQLException, RuntimeException)
879 : : {
880 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
881 : : return getGeneratedValuesFromLastInsert(
882 : 0 : m_pSettings, m_connection, m_lastOidInserted, m_lastTableInserted, m_lastQuery );
883 : : }
884 : :
885 : :
886 : : }
|